diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index f5bee3a..c5abd79 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -1,9 +1,7 @@ -use self::namespace::{GlobalNamespace, TypeDef}; - -pub mod namespace; +use crate::namespace::{typedef::TypeDef, GlobalNamespace}; pub fn initialise_globals() -> GlobalNamespace { - let mut ns = GlobalNamespace::init(); + let ns = GlobalNamespace::init(); let numeric = ns.register_trait("Numeric").unwrap(); diff --git a/src/builtins/namespace.rs b/src/builtins/namespace.rs index d420de2..8b13789 100644 --- a/src/builtins/namespace.rs +++ b/src/builtins/namespace.rs @@ -1,299 +1 @@ -use std::{ - cell::RefCell, - collections::{HashMap, HashSet}, - rc::Rc, -}; -pub struct GlobalNamespace { - // types - // constants - // groups (maybe global data namespace that has groups as subset?) - types: RefCell>, - traits: RefCell>, - type_namespace: RefCell>, - commands: RefCell>, - data_namespace: RefCell>, -} - -enum TypeNamespaceId { - Types(usize), - Traits(usize), -} - -enum DataNamespaceId { - Commands(usize), - Globals(usize), -} - -impl GlobalNamespace { - pub fn init() -> Self { - Self { - types: RefCell::new(Vec::new()), - traits: RefCell::new(Vec::new()), - type_namespace: RefCell::new(HashMap::new()), - commands: RefCell::new(Vec::new()), - data_namespace: RefCell::new(HashMap::new()), - } - } - pub fn register_type(&self, name: &str) -> Result { - if self.type_namespace.borrow().contains_key(name) { - Err(TypeRegistrationError::NameAlreadyExists) - } else { - self.types.borrow_mut().push(InternalType { - traits: RefCell::new(HashSet::new()), - name: name.to_owned(), - }); - let id = self.types.borrow().len() - 1; - let _ = self - .type_namespace - .borrow_mut() - .insert(name.to_owned(), TypeNamespaceId::Types(id)); - Ok(Type { - id, - namespace: self, - }) - } - } - - pub fn register_trait(&self, name: &str) -> Result { - if self.type_namespace.borrow().contains_key(name) { - Err(TypeRegistrationError::NameAlreadyExists) - } else { - self.traits.borrow_mut().push(InternalTrait { - types: RefCell::new(HashSet::new()), - name: name.to_owned(), - }); - let id = self.traits.borrow().len() - 1; - let _ = self - .type_namespace - .borrow_mut() - .insert(name.to_owned(), TypeNamespaceId::Traits(id)); - Ok(Trait { - id, - namespace: &*self, - }) - } - } - - pub fn register_command( - &self, - name: &str, - input: Option, - output: Option, - ) -> Result { - if self.data_namespace.borrow().contains_key(name) { - Err(TypeRegistrationError::NameAlreadyExists) - } else { - self.commands.borrow_mut().push(InternalCommand { - name: name.to_owned(), - input: input.map(|def| def.into()), - output: output.map(|def| def.into()), - }); - let id = self.traits.borrow().len() - 1; - let _ = self - .data_namespace - .borrow_mut() - .insert(name.to_owned(), DataNamespaceId::Commands(id)); - Ok(Command { - id, - namespace: self, - }) - } - } - - pub fn get_type(&self, id: usize) -> Option { - if self.types.borrow().len() > id { - Some(Type { - id, - namespace: self, - }) - } else { - None - } - } - - pub fn get_trait(&self, id: usize) -> Option { - if self.traits.borrow().len() > id { - Some(Trait { - id, - namespace: self, - }) - } else { - None - } - } - - pub fn get_command(&self, id: usize) -> Option { - if self.commands.borrow().len() > id { - Some(Command { - id, - namespace: self, - }) - } else { - None - } - } - - pub fn get_type_by_name(&self, name: &str) -> Option { - if let Some(TypeNamespaceId::Types(id)) = self.type_namespace.borrow().get(name) { - Some(Type { - id: *id, - namespace: self, - }) - } else { - None - } - } - - pub fn get_trait_by_name(&self, name: &str) -> Option { - if let Some(TypeNamespaceId::Traits(id)) = self.type_namespace.borrow().get(name) { - Some(Trait { - id: *id, - namespace: self, - }) - } else { - None - } - } - - pub fn get_command_by_name(&self, name: &str) -> Option { - if let Some(DataNamespaceId::Commands(id)) = self.data_namespace.borrow().get(name) { - Some(Command { - id: *id, - namespace: self, - }) - } else { - None - } - } -} - -#[derive(Debug)] -pub enum TypeRegistrationError { - NameAlreadyExists, -} - -#[derive(Clone, Copy)] -pub struct Type<'a> { - id: usize, - namespace: &'a GlobalNamespace, -} - -impl<'a> Type<'a> { - pub fn add_trait(&self, to_add: &'a Trait) { - let internal_self = &self.namespace.types.borrow()[self.id]; - - internal_self.traits.borrow_mut().insert(to_add.id); - self.namespace.traits.borrow_mut()[to_add.id] - .types - .borrow_mut() - .insert(self.id); - } - - pub fn has_trait(&self, to_check: &'a Trait) -> bool { - self.namespace.types.borrow()[self.id] - .traits - .borrow() - .contains(&to_check.id) - } -} - -struct InternalType { - traits: RefCell>, - name: String, -} - -#[derive(Clone, Copy)] -pub struct Trait<'a> { - id: usize, - namespace: &'a GlobalNamespace, -} - -struct InternalTrait { - // make resolution easier - types: RefCell>, - name: String, -} - -#[derive(Clone, Copy)] -pub struct Command<'a> { - id: usize, - namespace: &'a GlobalNamespace, -} - -impl<'a> Command<'a> { - pub fn get_input_types(&self) -> Option> { - self.namespace.commands.borrow()[self.id] - .input - .as_ref() - .map(|def| TypeDef::from_internal(self.namespace, def)) - } - pub fn get_output_types(&self) -> Option { - self.namespace.commands.borrow()[self.id] - .output - .as_ref() - .map(|def| TypeDef::from_internal(self.namespace, def)) - } -} - -struct InternalCommand { - name: String, - // gosh this is hacky - input: Option, - output: Option, -} - -/// the thing used for type annotations etc -/// stores type ids -pub enum TypeDef<'a> { - /// T - Type(Type<'a>), - Trait(Trait<'a>), - /// [ T ] - List(Vec>), - /// { name: T } or in group declarations [ name: T ] - Record(Vec<(String, TypeDef<'a>)>), -} - -impl<'a> TypeDef<'a> { - fn from_internal(ns: &'a GlobalNamespace, def: &InternalTypeDef) -> TypeDef<'a> { - match def { - InternalTypeDef::Single(id) => match id { - // safe to unwrap because this is only used with internal representations - TypeNamespaceId::Types(id) => TypeDef::Type(ns.get_type(*id).unwrap()), - TypeNamespaceId::Traits(id) => TypeDef::Trait(ns.get_trait(*id).unwrap()), - }, - InternalTypeDef::List(list) => TypeDef::List( - list.into_iter() - .map(|def| Self::from_internal(ns, def)) - .collect(), - ), - InternalTypeDef::Record(rec) => TypeDef::Record( - rec.into_iter() - .map(|(name, def)| (name.clone(), Self::from_internal(ns, def))) - .collect(), - ), - } - } -} - -enum InternalTypeDef { - Single(TypeNamespaceId), - List(Vec), - Record(Vec<(String, InternalTypeDef)>), -} - -impl From> for InternalTypeDef { - fn from(value: TypeDef) -> Self { - match value { - TypeDef::Type(val) => Self::Single(TypeNamespaceId::Types(val.id)), - TypeDef::Trait(val) => Self::Single(TypeNamespaceId::Traits(val.id)), - TypeDef::List(list) => Self::List(list.into_iter().map(|def| def.into()).collect()), - TypeDef::Record(rec) => Self::Record( - rec.into_iter() - .map(|(name, typ)| (name, typ.into())) - .collect(), - ), - } - } -} diff --git a/src/main.rs b/src/main.rs index cd023da..59fa176 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod builtins; mod lexer; +mod namespace; mod syntax; fn main() {} diff --git a/src/namespace/command.rs b/src/namespace/command.rs new file mode 100644 index 0000000..d835fd8 --- /dev/null +++ b/src/namespace/command.rs @@ -0,0 +1,31 @@ +use super::typedef::{InternalTypeDef, TypeDef}; + +use super::GlobalNamespace; + +#[derive(Clone, Copy)] +pub struct Command<'a> { + pub(super) id: usize, + pub(super) namespace: &'a GlobalNamespace, +} + +impl<'a> Command<'a> { + pub fn get_input_types(&self) -> Option> { + self.namespace.commands.borrow()[self.id] + .input + .as_ref() + .map(|def| TypeDef::from_internal(self.namespace, def)) + } + pub fn get_output_types(&self) -> Option { + self.namespace.commands.borrow()[self.id] + .output + .as_ref() + .map(|def| TypeDef::from_internal(self.namespace, def)) + } +} + +pub(super) struct InternalCommand { + pub(super) name: String, + // gosh this is hacky + pub(super) input: Option, + pub(super) output: Option, +} diff --git a/src/namespace/mod.rs b/src/namespace/mod.rs new file mode 100644 index 0000000..3edce2f --- /dev/null +++ b/src/namespace/mod.rs @@ -0,0 +1,182 @@ +use std::{ + cell::RefCell, + collections::{HashMap, HashSet}, +}; + +use self::{ + command::{Command, InternalCommand}, + r#trait::{InternalTrait, Trait}, + r#type::InternalType, + typedef::TypeDef, +}; + +mod command; +mod r#trait; +mod r#type; +pub mod typedef; + +pub struct GlobalNamespace { + types: RefCell>, + traits: RefCell>, + type_namespace: RefCell>, + commands: RefCell>, + data_namespace: RefCell>, +} + +enum TypeNamespaceId { + Types(usize), + Traits(usize), +} + +enum DataNamespaceId { + Commands(usize), + Globals(usize), +} + +impl GlobalNamespace { + pub fn init() -> Self { + Self { + types: RefCell::new(Vec::new()), + traits: RefCell::new(Vec::new()), + type_namespace: RefCell::new(HashMap::new()), + commands: RefCell::new(Vec::new()), + data_namespace: RefCell::new(HashMap::new()), + } + } + pub fn register_type(&self, name: &str) -> Result { + if self.type_namespace.borrow().contains_key(name) { + Err(NsRegistrationError::NameAlreadyExists) + } else { + self.types.borrow_mut().push(InternalType { + traits: RefCell::new(HashSet::new()), + name: name.to_owned(), + }); + let id = self.types.borrow().len() - 1; + let _ = self + .type_namespace + .borrow_mut() + .insert(name.to_owned(), TypeNamespaceId::Types(id)); + Ok(r#type::Type { + id, + namespace: self, + }) + } + } + + pub fn register_trait(&self, name: &str) -> Result { + if self.type_namespace.borrow().contains_key(name) { + Err(NsRegistrationError::NameAlreadyExists) + } else { + self.traits.borrow_mut().push(InternalTrait { + types: RefCell::new(HashSet::new()), + name: name.to_owned(), + }); + let id = self.traits.borrow().len() - 1; + let _ = self + .type_namespace + .borrow_mut() + .insert(name.to_owned(), TypeNamespaceId::Traits(id)); + Ok(Trait { + id, + namespace: self, + }) + } + } + + pub fn register_command( + &self, + name: &str, + input: Option, + output: Option, + ) -> Result { + if self.data_namespace.borrow().contains_key(name) { + Err(NsRegistrationError::NameAlreadyExists) + } else { + self.commands.borrow_mut().push(InternalCommand { + name: name.to_owned(), + input: input.map(|def| def.into()), + output: output.map(|def| def.into()), + }); + let id = self.traits.borrow().len() - 1; + let _ = self + .data_namespace + .borrow_mut() + .insert(name.to_owned(), DataNamespaceId::Commands(id)); + Ok(Command { + id, + namespace: self, + }) + } + } + + pub fn get_type(&self, id: usize) -> Option { + if self.types.borrow().len() > id { + Some(r#type::Type { + id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_trait(&self, id: usize) -> Option { + if self.traits.borrow().len() > id { + Some(Trait { + id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_command(&self, id: usize) -> Option { + if self.commands.borrow().len() > id { + Some(Command { + id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_type_by_name(&self, name: &str) -> Option { + if let Some(TypeNamespaceId::Types(id)) = self.type_namespace.borrow().get(name) { + Some(r#type::Type { + id: *id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_trait_by_name(&self, name: &str) -> Option { + if let Some(TypeNamespaceId::Traits(id)) = self.type_namespace.borrow().get(name) { + Some(Trait { + id: *id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_command_by_name(&self, name: &str) -> Option { + if let Some(DataNamespaceId::Commands(id)) = self.data_namespace.borrow().get(name) { + Some(Command { + id: *id, + namespace: self, + }) + } else { + None + } + } +} + +#[derive(Debug)] +pub enum NsRegistrationError { + NameAlreadyExists, +} diff --git a/src/namespace/trait.rs b/src/namespace/trait.rs new file mode 100644 index 0000000..47b8921 --- /dev/null +++ b/src/namespace/trait.rs @@ -0,0 +1,17 @@ +use std::collections::HashSet; + +use std::cell::RefCell; + +use super::GlobalNamespace; + +#[derive(Clone, Copy)] +pub struct Trait<'a> { + pub(super) id: usize, + pub(super) namespace: &'a GlobalNamespace, +} + +pub(super) struct InternalTrait { + // make resolution easier + pub(super) types: RefCell>, + pub(super) name: String, +} diff --git a/src/namespace/type.rs b/src/namespace/type.rs new file mode 100644 index 0000000..52df2de --- /dev/null +++ b/src/namespace/type.rs @@ -0,0 +1,37 @@ +use std::collections::HashSet; + +use std::cell::RefCell; + +use super::Trait; + +use super::GlobalNamespace; + +#[derive(Clone, Copy)] +pub struct Type<'a> { + pub(super) id: usize, + pub(super) namespace: &'a GlobalNamespace, +} + +impl<'a> Type<'a> { + pub fn add_trait(&self, to_add: &'a Trait) { + let internal_self = &self.namespace.types.borrow()[self.id]; + + internal_self.traits.borrow_mut().insert(to_add.id); + self.namespace.traits.borrow_mut()[to_add.id] + .types + .borrow_mut() + .insert(self.id); + } + + pub fn has_trait(&self, to_check: &'a Trait) -> bool { + self.namespace.types.borrow()[self.id] + .traits + .borrow() + .contains(&to_check.id) + } +} + +pub(super) struct InternalType { + pub(super) traits: RefCell>, + pub(super) name: String, +} diff --git a/src/namespace/typedef.rs b/src/namespace/typedef.rs new file mode 100644 index 0000000..81c9332 --- /dev/null +++ b/src/namespace/typedef.rs @@ -0,0 +1,56 @@ +use super::TypeNamespaceId; + +use super::GlobalNamespace; + +use super::r#trait::Trait; +use super::r#type::Type; + +pub enum TypeDef<'a> { + Type(Type<'a>), + Trait(Trait<'a>), + List(Vec>), + Record(Vec<(String, TypeDef<'a>)>), +} + +impl<'a> TypeDef<'a> { + pub(super) fn from_internal(ns: &'a GlobalNamespace, def: &InternalTypeDef) -> TypeDef<'a> { + match def { + InternalTypeDef::Single(id) => match id { + // safe to unwrap because this is only used with internal representations + TypeNamespaceId::Types(id) => TypeDef::Type(ns.get_type(*id).unwrap()), + TypeNamespaceId::Traits(id) => TypeDef::Trait(ns.get_trait(*id).unwrap()), + }, + InternalTypeDef::List(list) => TypeDef::List( + list.into_iter() + .map(|def| Self::from_internal(ns, def)) + .collect(), + ), + InternalTypeDef::Record(rec) => TypeDef::Record( + rec.into_iter() + .map(|(name, def)| (name.clone(), Self::from_internal(ns, def))) + .collect(), + ), + } + } +} + +pub(super) enum InternalTypeDef { + Single(TypeNamespaceId), + List(Vec), + Record(Vec<(String, InternalTypeDef)>), +} + +impl From> for InternalTypeDef { + fn from(value: TypeDef) -> Self { + match value { + TypeDef::Type(val) => Self::Single(TypeNamespaceId::Types(val.id)), + TypeDef::Trait(val) => Self::Single(TypeNamespaceId::Traits(val.id)), + TypeDef::List(list) => Self::List(list.into_iter().map(|def| def.into()).collect()), + TypeDef::Record(rec) => Self::Record( + rec.into_iter() + .map(|(name, typ)| (name, typ.into())) + .collect(), + ), + } + } +} diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 1d188bd..8a22b69 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -5,8 +5,6 @@ use logos::Span; use crate::lexer::Token; -use self::error::SyntaxError; - pub mod check; mod error;