From 243eb426c8161e63586ae197b9630a1c949f170d Mon Sep 17 00:00:00 2001 From: James Harton Date: Fri, 22 Feb 2019 23:08:15 +1300 Subject: [PATCH] Add constant values. --- huia-compiler/src/class.rs | 15 +++- huia-compiler/src/constant.rs | 155 ++++++++++++++++++++++++++++++++ huia-compiler/src/context.rs | 45 +++++----- huia-compiler/src/identifier.rs | 20 +++-- huia-compiler/src/lib.rs | 1 + huia-compiler/src/trait.rs | 15 +++- 6 files changed, 217 insertions(+), 34 deletions(-) create mode 100644 huia-compiler/src/constant.rs diff --git a/huia-compiler/src/class.rs b/huia-compiler/src/class.rs index 32683d1..54b3950 100644 --- a/huia-compiler/src/class.rs +++ b/huia-compiler/src/class.rs @@ -44,6 +44,15 @@ impl Classes { ClassId(elements.len()) } + pub fn find(&self, name: Identifier) -> Option { + let elements = self.0.read().unwrap(); + let class = elements.iter().find(|class| class.name() == name); + match class { + Some(class) => Some(class.id()), + None => None, + } + } + pub fn is_empty(&self) -> bool { let elements = self.0.read().unwrap(); elements.is_empty() @@ -127,8 +136,8 @@ mod test { fn set_name() { let mut context = Context::new(); let class = context.new_class("Marty McFly"); - assert_eq!(class.name(), context.get_identifier("Marty McFly")); - class.set_name(context.get_identifier("Doc Brown")); - assert_eq!(class.name(), context.get_identifier("Doc Brown")); + assert_eq!(class.name(), context.identifiers().get("Marty McFly")); + class.set_name(context.identifiers().get("Doc Brown")); + assert_eq!(class.name(), context.identifiers().get("Doc Brown")); } } diff --git a/huia-compiler/src/constant.rs b/huia-compiler/src/constant.rs new file mode 100644 index 0000000..d50d567 --- /dev/null +++ b/huia-compiler/src/constant.rs @@ -0,0 +1,155 @@ +use crate::class::ClassId; +use string_interner::{StringInterner, Sym}; + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct ConstantId(usize); + +impl From for usize { + fn from(data: ConstantId) -> usize { + data.0 + } +} + +impl From for ConstantId { + fn from(data: usize) -> ConstantId { + ConstantId(data) + } +} + +pub struct Constants { + values: Vec, + strings: StringInterner, +} + +impl Constants { + pub fn new() -> Constants { + Constants { + values: Vec::new(), + strings: StringInterner::default(), + } + } + + pub fn get(&self, id: ConstantId) -> Option<&Constant> { + match self.values.iter().nth(id.0) { + Some(constant) => Some(&constant), + None => None, + } + } + + pub fn new_i64(&mut self, class_id: ClassId, i: i64) -> ConstantId { + let value = ConstantInner::I64(i); + let constant = Constant { class_id, value }; + let id = self.values.len(); + self.values.push(constant); + ConstantId(id) + } + + pub fn get_i64(&self, id: ConstantId) -> Option { + let idx = id.0; + let constant = self.values[idx].clone(); + match constant.value { + ConstantInner::I64(i) => Some(i), + _ => None, + } + } + + pub fn new_f64(&mut self, class_id: ClassId, f: f64) -> ConstantId { + let value = ConstantInner::F64(f); + let constant = Constant { class_id, value }; + let id = self.values.len(); + self.values.push(constant); + ConstantId(id) + } + + pub fn get_f64(&self, id: ConstantId) -> Option { + let idx = id.0; + let constant = self.values[idx].clone(); + match constant.value { + ConstantInner::F64(f) => Some(f), + _ => None, + } + } + + pub fn new_string(&mut self, class_id: ClassId, s: &str) -> ConstantId { + let sym = self.strings.get_or_intern(s); + let value = ConstantInner::String(sym); + let constant = Constant { class_id, value }; + let id = self.values.len(); + self.values.push(constant); + ConstantId(id) + } + + pub fn get_string(&self, id: ConstantId) -> Option<&str> { + let idx = id.0; + let constant = self.values[idx].clone(); + match constant.value { + ConstantInner::String(s) => self.strings.resolve(s), + _ => None, + } + } + + pub fn is_empty(&self) -> bool { + self.values.is_empty() && self.strings.is_empty() + } +} + +#[derive(Debug, PartialEq, PartialOrd, Clone)] +pub struct Constant { + class_id: ClassId, + value: ConstantInner, +} + +impl Constant { + pub fn is_i64(&self) -> bool { + match self.value { + ConstantInner::I64(_) => true, + _ => false, + } + } + + pub fn is_f64(&self) -> bool { + match self.value { + ConstantInner::F64(_) => true, + _ => false, + } + } + + pub fn is_string(&self) -> bool { + match self.value { + ConstantInner::String(_) => true, + _ => false, + } + } +} + +#[derive(Debug, PartialEq, PartialOrd, Clone)] +enum ConstantInner { + I64(i64), + F64(f64), + String(Sym), +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test() { + let mut constants = Constants::new(); + assert!(constants.is_empty()); + + let class_id = ClassId::from(0); + + let i = constants.new_i64(class_id, 123); + assert!(constants.get(i).unwrap().is_i64()); + assert_eq!(constants.get_i64(i).unwrap(), 123); + + let f = constants.new_f64(class_id, 1.21); + assert!(constants.get(f).unwrap().is_f64()); + assert_eq!(constants.get_f64(f).unwrap(), 1.21); + + let s = constants.new_string(class_id, "Marty McFly"); + assert!(constants.get(s).unwrap().is_string()); + assert_eq!(constants.get_string(s).unwrap(), "Marty McFly"); + } +} diff --git a/huia-compiler/src/context.rs b/huia-compiler/src/context.rs index de86ba9..b06a29f 100644 --- a/huia-compiler/src/context.rs +++ b/huia-compiler/src/context.rs @@ -1,4 +1,5 @@ use crate::class::{Class, ClassId, Classes}; +use crate::constant::Constants; use crate::identifier::{Identifier, Identifiers}; use crate::r#trait::{Trait, TraitId, Traits}; @@ -6,6 +7,7 @@ pub struct Context { classes: Classes, traits: Traits, identifiers: Identifiers, + constants: Constants, } impl Context { @@ -14,6 +16,7 @@ impl Context { classes: Classes::new(), traits: Traits::new(), identifiers: Identifiers::new(), + constants: Constants::new(), } } @@ -25,10 +28,6 @@ impl Context { self.classes.get(id).unwrap() } - pub fn get_class(&self, id: ClassId) -> Option { - self.classes.get(id) - } - pub fn new_trait(&mut self, name: &str) -> Trait { let name = self.identifiers.get(name); let id = self.traits.next_id(); @@ -37,22 +36,26 @@ impl Context { self.traits.get(id).unwrap() } - pub fn get_trait(&self, id: TraitId) -> Option { - self.traits.get(id) - } - - pub fn get_identifier(&mut self, value: &str) -> Identifier { - self.identifiers.get(value) - } - - pub fn get_identifier_value(&self, identifier: Identifier) -> Option<&str> { - self.identifiers.resolve(identifier) - } - pub fn is_empty(&self) -> bool { // Traits and Classes must be empty if identifiers is empty because // classes and traits must be initialised with identifier names. - self.identifiers.is_empty() + self.identifiers.is_empty() && self.constants.is_empty() + } + + pub fn identifiers(&self) -> &Identifiers { + &self.identifiers + } + + pub fn constants(&self) -> &Constants { + &self.constants + } + + pub fn classes(&self) -> &Classes { + &self.classes + } + + pub fn traits(&self) -> &Traits { + &self.traits } } @@ -64,14 +67,14 @@ mod test { fn new() { let mut context = Context::new(); let class0 = context.new_class("Marty McFly"); - let class1 = context.get_class(class0.id()).unwrap(); + let class1 = context.classes().get(class0.id()).unwrap(); assert_eq!(class0, class1); let tr0 = context.new_trait("Doc Brown"); - let tr1 = context.get_trait(tr0.id()).unwrap(); + let tr1 = context.traits().get(tr0.id()).unwrap(); assert_eq!(tr0, tr1); - let id = context.get_identifier("Einstein Brown"); - assert_eq!(context.get_identifier_value(id).unwrap(), "Einstein Brown"); + let id = context.identifiers().get("Einstein Brown"); + assert_eq!(context.identifiers().resolve(id).unwrap(), "Einstein Brown"); } } diff --git a/huia-compiler/src/identifier.rs b/huia-compiler/src/identifier.rs index 1dcf2d5..ad66ba2 100644 --- a/huia-compiler/src/identifier.rs +++ b/huia-compiler/src/identifier.rs @@ -1,26 +1,32 @@ +use std::sync::RwLock; use string_interner::{StringInterner, Sym}; #[derive(Debug, Clone, Hash, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Identifier(Sym); -pub struct Identifiers(StringInterner); +pub struct Identifiers(RwLock>); impl Identifiers { pub fn new() -> Identifiers { - Identifiers(StringInterner::default()) + Identifiers(RwLock::new(StringInterner::default())) } - pub fn get(&mut self, value: &str) -> Identifier { - let sym = self.0.get_or_intern(value); + pub fn get(&self, value: &str) -> Identifier { + let mut identifiers = self.0.write().unwrap(); + let sym = identifiers.get_or_intern(value); Identifier(sym) } - pub fn resolve(&self, identifier: Identifier) -> Option<&str> { - self.0.resolve(identifier.0) + pub fn resolve(&self, identifier: Identifier) -> Option { + let identifiers = self.0.read().unwrap(); + match identifiers.resolve(identifier.0) { + Some(s) => Some(s.to_string()), + None => None, + } } pub fn is_empty(&self) -> bool { - self.0.is_empty() + self.0.read().unwrap().is_empty() } } diff --git a/huia-compiler/src/lib.rs b/huia-compiler/src/lib.rs index c1978bb..80ef8d0 100644 --- a/huia-compiler/src/lib.rs +++ b/huia-compiler/src/lib.rs @@ -3,6 +3,7 @@ extern crate string_interner; extern crate wrc; mod class; +mod constant; mod context; mod identifier; mod r#trait; diff --git a/huia-compiler/src/trait.rs b/huia-compiler/src/trait.rs index 1ea375f..d2329af 100644 --- a/huia-compiler/src/trait.rs +++ b/huia-compiler/src/trait.rs @@ -44,6 +44,15 @@ impl Traits { TraitId(elements.len()) } + pub fn find(&self, name: Identifier) -> Option { + let elements = self.0.read().unwrap(); + let tr = elements.iter().find(|tr| tr.name() == name); + match tr { + Some(tr) => Some(tr.id()), + None => None, + } + } + pub fn is_empty(&self) -> bool { let elements = self.0.read().unwrap(); elements.is_empty() @@ -127,8 +136,8 @@ mod test { fn set_name() { let mut context = Context::new(); let tr = context.new_trait("Marty McFly"); - assert_eq!(tr.name(), context.get_identifier("Marty McFly")); - tr.set_name(context.get_identifier("Doc Brown")); - assert_eq!(tr.name(), context.get_identifier("Doc Brown")); + assert_eq!(tr.name(), context.identifiers().get("Marty McFly")); + tr.set_name(context.identifiers().get("Doc Brown")); + assert_eq!(tr.name(), context.identifiers().get("Doc Brown")); } }