diff --git a/huia-compiler/Cargo.toml b/huia-compiler/Cargo.toml index 9c5d8b4..afe7d3a 100644 --- a/huia-compiler/Cargo.toml +++ b/huia-compiler/Cargo.toml @@ -5,3 +5,4 @@ authors = ["James Harton "] edition = "2018" [dependencies] +wrc = "0.3.0" diff --git a/huia-compiler/src/lib.rs b/huia-compiler/src/lib.rs index 35a7398..89285dd 100644 --- a/huia-compiler/src/lib.rs +++ b/huia-compiler/src/lib.rs @@ -1,3 +1,4 @@ -mod context; +extern crate wrc; +// mod context; mod scope; -mod symbol; +// mod symbol; diff --git a/huia-compiler/src/scope.rs b/huia-compiler/src/scope.rs deleted file mode 100644 index b1fca4c..0000000 --- a/huia-compiler/src/scope.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::symbol::Symbol; -use std::collections::HashMap; - -pub struct Scope { - symbols: HashMap, -} - -impl Scope { - pub fn define(&mut self, symbol: Symbol) { - self.symbols.insert(symbol.identifier().to_string(), symbol); - } - - pub fn reference(&self, identifier: &str) -> Option<&Symbol> { - self.symbols.get(identifier) - } - - pub fn has_symbol(&self, identifier: &str) -> bool { - self.symbols.contains_key(identifier) - } - - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } -} - -impl Default for Scope { - fn default() -> Scope { - Scope { - symbols: HashMap::new(), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn add_and_get() { - let mut scope = Scope::default(); - let symbol = Symbol::local("marty"); - assert!(scope.is_empty()); - assert!(!scope.has_symbol("marty")); - scope.define(symbol.clone()); - assert!(scope.has_symbol("marty")); - assert_eq!(scope.reference("marty").unwrap(), &symbol); - } -} diff --git a/huia-compiler/src/scope/local.rs b/huia-compiler/src/scope/local.rs new file mode 100644 index 0000000..9e1c706 --- /dev/null +++ b/huia-compiler/src/scope/local.rs @@ -0,0 +1,47 @@ +use super::{Identifiable, Type}; +use std::ops::{Deref, DerefMut}; +use wrc::WRC; + +#[derive(Debug, Clone)] +pub struct Local(WRC); + +impl Local { + fn new(identifier: &str, r#type: Type) -> Local { + Local(WRC::new(LocalInner { + identifier: identifier.to_string(), + r#type: r#type, + })) + } +} + +impl Deref for Local { + type Target = WRC; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Local { + fn deref_mut(&mut self) -> &mut WRC { + &mut self.0 + } +} + +#[derive(Debug, Clone)] +pub struct LocalInner { + identifier: String, + r#type: Type, +} + +impl LocalInner { + fn r#type(&self) -> Type { + self.r#type.clone() + } +} + +impl Identifiable for Local { + fn identifier(&self) -> &str { + &self.identifier + } +} diff --git a/huia-compiler/src/scope/method.rs b/huia-compiler/src/scope/method.rs new file mode 100644 index 0000000..84d3fb6 --- /dev/null +++ b/huia-compiler/src/scope/method.rs @@ -0,0 +1,100 @@ +use super::{Identifiable, Local, Scope, Type}; +use std::collections::HashMap; +use std::ops::{Deref, DerefMut}; +use wrc::WRC; + +#[derive(Debug, Clone)] +pub struct Method(WRC); + +#[derive(Debug, Clone)] +pub struct MethodInner { + identifier: String, + result: Type, + visibility: Visibility, + arguments: HashMap, + locals: HashMap, +} + +impl Method { + fn new(identifier: &str, result: Type, public: bool, arguments: Vec) -> Method { + let visibility = match public { + true => Visibility::Public, + false => Visibility::Private, + }; + + let mut args_hash = HashMap::new(); + for local in arguments { + args_hash.insert(local.identifier().to_string(), local); + } + + Method(WRC::new(MethodInner { + identifier: identifier.to_string(), + result, + visibility, + arguments: args_hash, + locals: HashMap::new(), + })) + } +} + +impl Deref for Method { + type Target = WRC; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Method { + fn deref_mut(&mut self) -> &mut WRC { + &mut self.0 + } +} + +impl MethodInner { + pub fn result(&self) -> Type { + self.result.clone() + } + + pub fn is_public(&self) -> bool { + match self.visibility { + Visibility::Public => true, + _ => false, + } + } + + pub fn is_private(&self) -> bool { + match self.visibility { + Visibility::Private => true, + _ => false, + } + } +} + +#[derive(Debug, Clone)] +pub enum Visibility { + Public, + Private, +} + +impl Identifiable for MethodInner { + fn identifier(&self) -> &str { + &self.identifier + } +} + +impl Scope for MethodInner { + fn define(&mut self, local: Local) { + self.locals.insert(local.identifier().to_string(), local); + } + + fn reference(&self, identifier: &str) -> Option { + match self.locals.get(identifier) { + Some(local) => Some(local.clone()), + None => match self.arguments.get(identifier) { + Some(local) => Some(local.clone()), + None => None, + }, + } + } +} diff --git a/huia-compiler/src/scope/mod.rs b/huia-compiler/src/scope/mod.rs new file mode 100644 index 0000000..10f8436 --- /dev/null +++ b/huia-compiler/src/scope/mod.rs @@ -0,0 +1,30 @@ +use std::collections::HashMap; +use wrc::WRC; + +mod local; +mod method; +mod r#trait; +mod r#type; +pub use local::Local; +pub use method::Method; +pub use r#trait::Trait; +pub use r#type::Type; + +pub enum Constant { + Type(Type), + Trait(Trait), +} + +pub struct Context { + globals: Constant, +} + +pub trait Scope { + fn define(&mut self, symbol: T); + + fn reference(&self, identifier: &str) -> Option; +} + +pub trait Identifiable { + fn identifier(&self) -> &str; +} diff --git a/huia-compiler/src/scope/trait.rs b/huia-compiler/src/scope/trait.rs new file mode 100644 index 0000000..69b26d2 --- /dev/null +++ b/huia-compiler/src/scope/trait.rs @@ -0,0 +1,66 @@ +use super::{Identifiable, Method, Scope}; +use std::collections::HashMap; +use std::ops::{Deref, DerefMut}; +use wrc::WRC; + +#[derive(Debug, Clone)] +pub struct Trait(WRC); + +impl Trait { + pub fn new(identifier: &str) -> Trait { + Trait(WRC::new(TraitInner { + identifier: identifier.to_string(), + public_methods: HashMap::new(), + private_methods: HashMap::new(), + })) + } +} + +impl Deref for Trait { + type Target = WRC; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Trait { + fn deref_mut(&mut self) -> &mut WRC { + &mut self.0 + } +} + +#[derive(Debug, Clone)] +pub struct TraitInner { + identifier: String, + public_methods: HashMap, + private_methods: HashMap, +} + +impl Identifiable for TraitInner { + fn identifier(&self) -> &str { + &self.identifier + } +} + +impl Scope for TraitInner { + fn define(&mut self, method: Method) { + if method.is_public() { + self.public_methods + .insert(method.identifier().to_string(), method); + } else { + self.private_methods + .insert(method.identifier().to_string(), method); + } + } + + fn reference(&self, identifier: &str) -> Option { + match self.public_methods.get(identifier) { + Some(method) => Some(method.clone()), + None => match self.private_methods.get(identifier) { + Some(method) => Some(method.clone()), + None => None, + }, + } + } +} diff --git a/huia-compiler/src/scope/type.rs b/huia-compiler/src/scope/type.rs new file mode 100644 index 0000000..aaf6442 --- /dev/null +++ b/huia-compiler/src/scope/type.rs @@ -0,0 +1,101 @@ +use super::{Identifiable, Method, Scope, Trait}; +use std::collections::HashMap; +use wrc::WRC; + +#[derive(Debug, Clone)] +pub struct Type(WRC); + +impl Type { + fn new(identifier: &str) -> Type { + Type(WRC::new(TypeInner { + identifier: identifier.to_string(), + public_methods: HashMap::new(), + private_methods: HashMap::new(), + traits: HashMap::new(), + })) + } +} + +#[derive(Debug, Clone)] +pub struct TypeInner { + identifier: String, + public_methods: HashMap, + private_methods: HashMap, + traits: HashMap, +} + +impl Scope for Type { + fn define(&mut self, method: Method) { + self.0.define(method); + } + + fn reference(&self, identifier: &str) -> Option { + self.0.reference(identifier) + } +} + +impl Identifiable for Type { + fn identifier(&self) -> &str { + self.0.identifier() + } +} + +impl Scope for TypeInner { + fn define(&mut self, method: Method) { + if method.is_public() { + self.public_methods + .insert(method.identifier().to_string(), method); + } else { + self.private_methods + .insert(method.identifier().to_string(), method); + } + } + + fn reference(&self, identifier: &str) -> Option { + match self.public_methods.get(identifier) { + Some(method) => Some(method.clone()), + None => match self.private_methods.get(identifier) { + Some(method) => Some(method.clone()), + None => None, + }, + } + } +} + +impl Scope for TypeInner { + fn define(&mut self, r#trait: Trait) { + self.traits + .insert(r#trait.identifier().to_string(), r#trait); + } + + fn reference(&self, identifier: &str) -> Option { + match self.traits.get(identifier) { + Some(r#trait) => Some(r#trait.clone()), + None => None, + } + } +} + +impl Identifiable for TypeInner { + fn identifier(&self) -> &str { + &self.identifier + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_new() { + let ty = Type::new("Marty.McFly"); + assert_eq!(ty.identifier(), "Marty.McFly"); + } + + #[test] + fn trait_scope() { + let tr = Trait::new("Character"); + let mut ty = Type::new("Marty.McFly"); + ty.define(tr); + } +}