Add mem and obj modules, move to nightly
* mem and obj modules are roughly divided between doing memory-specific things and object-specific things * Box::new_uninit() is a nightly feature and it's quite useful, so I'm enabling that for now * Check out src/obj/attrs.rs for possible undefined behavior in the Attrs::new() function. I'm sure it'll be just fine. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
#![feature(new_uninit)]
|
||||||
|
|
||||||
mod syn;
|
mod syn;
|
||||||
|
mod obj;
|
||||||
|
mod mem;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
|
|||||||
71
src/mem/basic.rs
Normal file
71
src/mem/basic.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use crate::{
|
||||||
|
mem::{
|
||||||
|
gc::Gc,
|
||||||
|
intern::Intern,
|
||||||
|
ptr::{DynRef, ObjCell, ObjRef},
|
||||||
|
},
|
||||||
|
obj::{ctx::ObjCtx, Obj, Str, Sym},
|
||||||
|
};
|
||||||
|
use std::{collections::HashMap, ptr::NonNull};
|
||||||
|
|
||||||
|
pub struct BasicGc {
|
||||||
|
objects: Vec<Box<ObjCell<dyn Obj>>>,
|
||||||
|
strs: HashMap<String, ObjRef<Str>>,
|
||||||
|
syms: HashMap<String, Sym>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gc for BasicGc {
|
||||||
|
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O> {
|
||||||
|
let obj_cell = Box::new(ObjCell::new(obj));
|
||||||
|
let obj_ptr = &*obj_cell as *const _ as *mut _;
|
||||||
|
self.objects.push(obj_cell);
|
||||||
|
ObjRef::new(NonNull::new(obj_ptr).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>) {
|
||||||
|
self.objects.push(owned);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark(&mut self, alive: &[DynRef]) {
|
||||||
|
for obj in alive.iter() {
|
||||||
|
obj.borrow().mark();
|
||||||
|
}
|
||||||
|
// TODO : where should interned strings be marked?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sweep(&mut self) {
|
||||||
|
// sweep
|
||||||
|
self.objects.retain(|cell| {
|
||||||
|
let obj = cell.borrow();
|
||||||
|
!obj.is_marked()
|
||||||
|
});
|
||||||
|
// unmark all objects
|
||||||
|
self.objects
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|cell| cell.borrow().unmark());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Intern for BasicGc {
|
||||||
|
fn get_str(&self, s: &str) -> Option<ObjRef<Str>> {
|
||||||
|
self.strs.get(s).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_str(&mut self, ctx: &mut ObjCtx, s: &str) -> ObjRef<Str> {
|
||||||
|
*self.strs.entry(s.to_string())
|
||||||
|
.or_insert_with(|| {
|
||||||
|
let s = Str::new(ctx, s.to_string());
|
||||||
|
ctx.gc_mut().alloc(s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_sym(&self, s: &str) -> Option<Sym> {
|
||||||
|
self.syms.get(s).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_sym(&mut self, s: &str) -> Sym {
|
||||||
|
let len = self.syms.len();
|
||||||
|
*self.syms.entry(s.to_string())
|
||||||
|
.or_insert_with(|| len)
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/mem/gc.rs
Normal file
22
src/mem/gc.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use crate::{
|
||||||
|
obj::prelude::*,
|
||||||
|
mem::{
|
||||||
|
ptr::ObjCell,
|
||||||
|
intern::Intern,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait Gc: Intern {
|
||||||
|
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O>;
|
||||||
|
|
||||||
|
fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>);
|
||||||
|
|
||||||
|
fn mark(&mut self, alive: &[DynRef]) {
|
||||||
|
for obj in alive.iter() {
|
||||||
|
obj.borrow_mut().mark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sweep(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
15
src/mem/intern.rs
Normal file
15
src/mem/intern.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use crate::{
|
||||||
|
mem::ptr::ObjRef,
|
||||||
|
obj::{
|
||||||
|
ctx::ObjCtx,
|
||||||
|
Str, Sym,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait Intern {
|
||||||
|
fn get_str(&self, s: &str) -> Option<ObjRef<Str>>;
|
||||||
|
fn add_str(&mut self, ctx: &mut ObjCtx, s: &str) -> ObjRef<Str>;
|
||||||
|
|
||||||
|
fn get_sym(&self, s: &str) -> Option<Sym>;
|
||||||
|
fn add_sym(&mut self, s: &str) -> Sym;
|
||||||
|
}
|
||||||
16
src/mem/mod.rs
Normal file
16
src/mem/mod.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
mod basic;
|
||||||
|
pub mod intern;
|
||||||
|
pub mod gc;
|
||||||
|
pub mod ptr;
|
||||||
|
|
||||||
|
pub use self::basic::BasicGc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::mem::{
|
||||||
|
alloc::Alloc,
|
||||||
|
gc::Gc,
|
||||||
|
ptr::*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
130
src/mem/ptr.rs
Normal file
130
src/mem/ptr.rs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
use crate::obj::Obj;
|
||||||
|
use std::{
|
||||||
|
any,
|
||||||
|
cell::RefCell,
|
||||||
|
fmt::{self, Debug, Formatter},
|
||||||
|
ops::Deref,
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type DynRef = ObjRef<dyn Obj>;
|
||||||
|
|
||||||
|
pub struct ObjRef<O>
|
||||||
|
where O: Obj + ?Sized
|
||||||
|
{
|
||||||
|
ptr: NonNull<ObjCell<O>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> ObjRef<O>
|
||||||
|
where O: Obj + ?Sized
|
||||||
|
{
|
||||||
|
pub fn new(ptr: NonNull<ObjCell<O>>) -> Self {
|
||||||
|
ObjRef { ptr }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ptr(&self) -> *const ObjCell<O> {
|
||||||
|
self.ptr.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> ObjRef<O>
|
||||||
|
where O: Obj
|
||||||
|
{
|
||||||
|
pub fn as_dyn(&self) -> ObjRef<dyn Obj> {
|
||||||
|
let ptr = self.as_ptr() as *const ObjCell<dyn Obj>;
|
||||||
|
ObjRef::new(NonNull::new(ptr as *mut _).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> Deref for ObjRef<O>
|
||||||
|
where O: Obj + ?Sized
|
||||||
|
{
|
||||||
|
type Target = RefCell<O>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
// Safe, so long as there are no dangling pointers from the GC
|
||||||
|
unsafe { &*self.as_ptr() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> Clone for ObjRef<O>
|
||||||
|
where O: Obj + ?Sized
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
ObjRef { ptr: self.ptr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> Copy for ObjRef<O>
|
||||||
|
where O: Obj + ?Sized
|
||||||
|
{}
|
||||||
|
|
||||||
|
impl<O> Debug for ObjRef<O>
|
||||||
|
where O: Obj + Debug + ?Sized
|
||||||
|
{
|
||||||
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "<{} object at {:#x}>", any::type_name::<O>(), self.as_ptr() as *const () as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ObjRef<dyn Obj> {
|
||||||
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "<? object at {:#x}>", self.as_ptr() as *const () as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Comparison impls
|
||||||
|
//
|
||||||
|
impl<O> PartialEq for ObjRef<O>
|
||||||
|
where
|
||||||
|
O: Obj + ?Sized + PartialEq,
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.borrow().eq(&other.borrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> Eq for ObjRef<O> where O: Obj + ?Sized + Eq {}
|
||||||
|
|
||||||
|
impl<O> PartialOrd for ObjRef<O>
|
||||||
|
where
|
||||||
|
O: Obj + ?Sized + PartialOrd,
|
||||||
|
{
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
self.borrow().partial_cmp(&other.borrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O> Ord for ObjRef<O>
|
||||||
|
where
|
||||||
|
O: Obj + ?Sized + Ord,
|
||||||
|
{
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
self.borrow().cmp(&other.borrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ObjCell
|
||||||
|
//
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ObjCell<O: Obj + ?Sized> {
|
||||||
|
cell: RefCell<O>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O: Obj> ObjCell<O> {
|
||||||
|
pub fn new(obj: O) -> Self {
|
||||||
|
ObjCell {
|
||||||
|
cell: RefCell::new(obj),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O: Obj + ?Sized> Deref for ObjCell<O> {
|
||||||
|
type Target = RefCell<O>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.cell
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/obj/attrs.rs
Normal file
86
src/obj/attrs.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
use crate::{
|
||||||
|
mem::ptr::{DynRef, ObjCell},
|
||||||
|
obj::prelude::*,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
cell::Cell,
|
||||||
|
mem::MaybeUninit,
|
||||||
|
ptr::{self, NonNull},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Attrs {
|
||||||
|
attrs: Vec<(Sym, DynRef)>,
|
||||||
|
marked: Cell<bool>,
|
||||||
|
this: ObjRef<Attrs>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attrs {
|
||||||
|
pub fn new(ctx: &mut ObjCtx) -> Self {
|
||||||
|
let obj: Box<ObjCell<Attrs>> = unsafe {
|
||||||
|
let mut obj: Box<MaybeUninit<ObjCell<Attrs>>> = Box::new_uninit();
|
||||||
|
// maybe UB? taking away the uninit right before it's initialized may be bad
|
||||||
|
let this = &*obj as *const _ as *const ObjCell<Attrs>;
|
||||||
|
|
||||||
|
obj.as_mut_ptr().write(ObjCell::new(Attrs {
|
||||||
|
attrs: Default::default(),
|
||||||
|
marked: Cell::new(false),
|
||||||
|
this: ObjRef::new(NonNull::new(this as *mut _).unwrap()),
|
||||||
|
}));
|
||||||
|
|
||||||
|
obj.assume_init()
|
||||||
|
};
|
||||||
|
|
||||||
|
let attrs = {
|
||||||
|
let obj_ref: &Attrs = &obj.borrow();
|
||||||
|
assert!(
|
||||||
|
ptr::eq(&*obj as *const _, obj_ref.this.as_ptr()),
|
||||||
|
"Attr 'this' member does not point to itself"
|
||||||
|
);
|
||||||
|
obj_ref.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the object to the allocator pool
|
||||||
|
ctx.gc_mut().add_obj(obj);
|
||||||
|
|
||||||
|
attrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for Attrs {
|
||||||
|
fn attrs(&self) -> ObjRef<Attrs> {
|
||||||
|
self.this
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_marked(&self) -> bool {
|
||||||
|
self.marked.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark(&self) {
|
||||||
|
if self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(true);
|
||||||
|
self.attrs.iter().for_each(|(_, v)| v.borrow().mark());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmark(&self) {
|
||||||
|
if !self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(false);
|
||||||
|
self.attrs.iter().for_each(|(_, v)| v.borrow().unmark());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_attrs_new() {
|
||||||
|
/*
|
||||||
|
use crate::mem::*;
|
||||||
|
let mut ctx = ObjCtx::new(
|
||||||
|
*/
|
||||||
|
}
|
||||||
26
src/obj/ctx.rs
Normal file
26
src/obj/ctx.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use crate::mem::{gc::Gc, BasicGc};
|
||||||
|
|
||||||
|
pub type DefaultGc = BasicGc;
|
||||||
|
|
||||||
|
pub struct ObjCtx<G=DefaultGc>
|
||||||
|
where
|
||||||
|
G: Gc,
|
||||||
|
{
|
||||||
|
gc: G,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G> ObjCtx<G>
|
||||||
|
where
|
||||||
|
G: Gc,
|
||||||
|
{
|
||||||
|
pub fn new(gc: G) -> Self {
|
||||||
|
ObjCtx { gc }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gc(&self) -> &G {
|
||||||
|
&self.gc
|
||||||
|
}
|
||||||
|
pub fn gc_mut(&mut self) -> &mut G {
|
||||||
|
&mut self.gc
|
||||||
|
}
|
||||||
|
}
|
||||||
61
src/obj/dict.rs
Normal file
61
src/obj/dict.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use crate::obj::prelude::*;
|
||||||
|
use std::{any::Any, cell::Cell};
|
||||||
|
|
||||||
|
pub type DictRef = ObjRef<Dict>;
|
||||||
|
|
||||||
|
pub struct Dict {
|
||||||
|
dict: Vec<(DynRef, DynRef)>,
|
||||||
|
attrs: ObjRef<Attrs>,
|
||||||
|
marked: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dict {
|
||||||
|
// TODO : base types need to be interned. This should probably be stored in a root namespace.
|
||||||
|
// * How to get the root namespace?
|
||||||
|
// * ObjCtx object that holds allocator, gc, root namespace, etc..?
|
||||||
|
// * How to create initial types?
|
||||||
|
pub fn new(ctx: &mut ObjCtx) -> Self {
|
||||||
|
todo!()
|
||||||
|
/*
|
||||||
|
Dict {
|
||||||
|
dict: Default::default(),
|
||||||
|
attrs: Attrs::new(ctx),
|
||||||
|
marked: Cell::new(false),
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for Dict {
|
||||||
|
fn attrs(&self) -> ObjRef<Attrs> {
|
||||||
|
self.attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_marked(&self) -> bool {
|
||||||
|
self.marked.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark(&self) {
|
||||||
|
if self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(true);
|
||||||
|
// TODO: dict
|
||||||
|
self.attrs.borrow().mark();
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmark(&self) {
|
||||||
|
if !self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(false);
|
||||||
|
// TODO: dict
|
||||||
|
self.attrs.borrow().unmark();
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/obj/error.rs
Normal file
13
src/obj/error.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crate::mem::ptr::DynRef;
|
||||||
|
use snafu::Snafu;
|
||||||
|
|
||||||
|
#[derive(Debug, Snafu)]
|
||||||
|
pub enum Error {
|
||||||
|
#[snafu(display("illegal attr key"))]
|
||||||
|
AttrKey {
|
||||||
|
key: DynRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
44
src/obj/mod.rs
Normal file
44
src/obj/mod.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
pub mod attrs;
|
||||||
|
pub mod ctx;
|
||||||
|
pub mod dict;
|
||||||
|
pub mod error;
|
||||||
|
//pub mod native_fun;
|
||||||
|
//pub mod num;
|
||||||
|
pub mod str;
|
||||||
|
pub mod sym {
|
||||||
|
pub type Sym = usize;
|
||||||
|
}
|
||||||
|
//pub mod ty;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::{
|
||||||
|
obj::{
|
||||||
|
Attrs, Dict, DictRef, Str, StrRef, Sym, ObjCtx, Obj,
|
||||||
|
},
|
||||||
|
mem::{
|
||||||
|
ptr::{ObjRef, DynRef},
|
||||||
|
intern::Intern,
|
||||||
|
gc::Gc,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::{
|
||||||
|
attrs::Attrs,
|
||||||
|
dict::{Dict, DictRef},
|
||||||
|
ctx::ObjCtx,
|
||||||
|
str::{Str, StrRef},
|
||||||
|
sym::Sym,
|
||||||
|
};
|
||||||
|
use crate::mem::ptr::ObjRef;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
pub trait Obj {
|
||||||
|
fn attrs(&self) -> ObjRef<Attrs>;
|
||||||
|
|
||||||
|
fn is_marked(&self) -> bool;
|
||||||
|
fn mark(&self);
|
||||||
|
fn unmark(&self);
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
}
|
||||||
27
src/obj/native_fun.rs
Normal file
27
src/obj/native_fun.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
use crate::obj::prelude::*;
|
||||||
|
|
||||||
|
pub type NativeFunPtr = *const fn();
|
||||||
|
|
||||||
|
pub struct NativeFun {
|
||||||
|
attrs: Attrs,
|
||||||
|
fn_ptr: NativeFunPtr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeFun {
|
||||||
|
pub fn new(ctx: &mut ObjCtx, name: StrRef, fn_ptr: NativeFunPtr) -> Self {
|
||||||
|
todo!()
|
||||||
|
/*
|
||||||
|
let attrs = Attrs::default();
|
||||||
|
NativeFun {
|
||||||
|
attrs,
|
||||||
|
fn_ptr,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
impl Obj for NativeFun {
|
||||||
|
fn get_attr(&self, key: &DynRef) -> Option<DynRef>
|
||||||
|
}
|
||||||
|
*/
|
||||||
0
src/obj/num.rs
Normal file
0
src/obj/num.rs
Normal file
64
src/obj/str.rs
Normal file
64
src/obj/str.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
use crate::obj::prelude::*;
|
||||||
|
use derivative::Derivative;
|
||||||
|
use std::{any::Any, cell::Cell};
|
||||||
|
|
||||||
|
pub type StrRef = ObjRef<Str>;
|
||||||
|
|
||||||
|
#[derive(Derivative)]
|
||||||
|
#[derivative(PartialEq, PartialOrd, Ord, Eq)]
|
||||||
|
pub struct Str {
|
||||||
|
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
||||||
|
attrs: ObjRef<Attrs>,
|
||||||
|
|
||||||
|
contents: String,
|
||||||
|
|
||||||
|
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
||||||
|
marked: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Str {
|
||||||
|
pub fn new(ctx: &mut ObjCtx, contents: String) -> Self {
|
||||||
|
todo!()
|
||||||
|
/*
|
||||||
|
Str {
|
||||||
|
attrs: Default::default(),
|
||||||
|
contents,
|
||||||
|
marked: Cell::new(false),
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contents(&self) -> &String {
|
||||||
|
&self.contents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for Str {
|
||||||
|
fn attrs(&self) -> ObjRef<Attrs> {
|
||||||
|
self.attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_marked(&self) -> bool {
|
||||||
|
self.marked.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark(&self) {
|
||||||
|
if self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(true);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmark(&self) {
|
||||||
|
if !self.is_marked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.marked.set(false);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/obj/ty.rs
Normal file
35
src/obj/ty.rs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
use crate::obj::prelude::*;
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
pub struct Ty {
|
||||||
|
marked: Cell<bool>,
|
||||||
|
this: ObjRef<Ty>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ty {
|
||||||
|
pub fn new(ctx: &mut ObjCtx) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for Ty {
|
||||||
|
fn attrs(&self) -> ObjRef<Attrs> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_marked(&self) -> bool {
|
||||||
|
self.marked.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark(&self) {
|
||||||
|
self.marked.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmark(&self) {
|
||||||
|
self.marked.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user