Skip to content

Commit

Permalink
Merge pull request #2 from Hirevo/feature/overlapping-fields
Browse files Browse the repository at this point in the history
Added static checks for overlapping fields
  • Loading branch information
Hirevo authored Jun 10, 2020
2 parents add440d + 1388730 commit 465cb27
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 18 deletions.
42 changes: 27 additions & 15 deletions som-interpreter/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,32 @@ pub struct Class {

impl Class {
/// Load up a class from its class definition from the AST.
pub fn from_class_def(defn: ClassDef) -> SOMRef<Class> {
let static_locals = defn
.static_locals
.iter()
.cloned()
.zip(std::iter::repeat(Value::Nil))
.collect();

let instance_locals = defn
.instance_locals
.iter()
.cloned()
.zip(std::iter::repeat(Value::Nil))
.collect();
pub fn from_class_def(defn: ClassDef) -> Result<SOMRef<Class>, String> {
let static_locals = {
let mut static_locals = IndexMap::new();
for field in defn.static_locals.iter() {
if static_locals.insert(field.clone(), Value::Nil).is_some() {
return Err(format!(
"{}: the field named '{}' is already defined in this class",
defn.name, field,
));
}
}
static_locals
};

let instance_locals = {
let mut instance_locals = IndexMap::new();
for field in defn.instance_locals.iter() {
if instance_locals.insert(field.clone(), Value::Nil).is_some() {
return Err(format!(
"{}: the field named '{}' is already defined in this class",
defn.name, field,
));
}
}
instance_locals
};

let static_class = Rc::new(RefCell::new(Self {
name: format!("{} class", defn.name),
Expand Down Expand Up @@ -117,7 +129,7 @@ impl Class {
static_class.borrow_mut().methods = static_methods;
instance_class.borrow_mut().methods = instance_methods;

instance_class
Ok(instance_class)
}

/// Get the class' name.
Expand Down
43 changes: 40 additions & 3 deletions som-interpreter/src/universe.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::fs;
use std::io;
Expand Down Expand Up @@ -248,7 +249,7 @@ impl Universe {
));
}

return Ok(Class::from_class_def(defn));
return Class::from_class_def(defn).map_err(Error::msg);
}

Err(anyhow!("could not find the '{}' system class", class_name))
Expand Down Expand Up @@ -295,9 +296,45 @@ impl Universe {
self.core.object_class.clone()
};

let class = Class::from_class_def(defn);
let class = Class::from_class_def(defn).map_err(Error::msg)?;
set_super_class(&class, &super_class, &self.core.metaclass_class);

fn has_duplicated_field(class: &SOMRef<Class>) -> Option<(String, (String, String))> {
let super_class_iterator = std::iter::successors(Some(class.clone()), |class| {
class.borrow().super_class()
});
let mut map = HashMap::<String, String>::new();
for class in super_class_iterator {
let class_name = class.borrow().name().to_string();
for (field, _) in class.borrow().locals.iter() {
let field_name = field.clone();
match map.entry(field_name.clone()) {
Entry::Occupied(entry) => {
return Some((field_name, (class_name, entry.get().clone())))
}
Entry::Vacant(v) => {
v.insert(class_name.clone());
}
}
}
}
return None;
}

if let Some((field, (c1, c2))) = has_duplicated_field(&class) {
return Err(anyhow!(
"the field named '{}' is defined more than once (by '{}' and '{}', where the latter inherits from the former)",
field, c1, c2,
));
}

if let Some((field, (c1, c2))) = has_duplicated_field(&class.borrow().class()) {
return Err(anyhow!(
"the field named '{}' is defined more than once (by '{}' and '{}', where the latter inherits from the former)",
field, c1, c2,
));
}

self.globals.insert(
class.borrow().name().to_string(),
Value::Class(class.clone()),
Expand Down Expand Up @@ -350,7 +387,7 @@ impl Universe {
self.core.object_class.clone()
};

let class = Class::from_class_def(defn);
let class = Class::from_class_def(defn).map_err(Error::msg)?;
set_super_class(&class, &super_class, &self.core.metaclass_class);

Ok(class)
Expand Down

0 comments on commit 465cb27

Please sign in to comment.