Skip to content

Commit

Permalink
Scan top-level imports and create dummy classes (#379)
Browse files Browse the repository at this point in the history
* Scan top-level imports and create dummy classes

In future we will need a system to get the actual
signature of these classes as well.
This is a future milestone.

* Add sad test for too many aliases
  • Loading branch information
JSAbrahams committed Dec 28, 2022
1 parent 63cc218 commit 708b67c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/check/context/clss/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ impl Hash for GenericClass {
}

impl GenericClass {
pub fn try_from_id(id: &AST) -> TypeResult<GenericClass> {
match &id.node {
Node::Id { lit } => {
Ok(GenericClass {
is_py_type: false,
name: StringName::from(lit.as_str()),
pos: id.pos,
concrete: true, // assume concrete for now
args: vec![],
fields: Default::default(),
functions: Default::default(),
parents: Default::default(),
})
}
_ => Err(vec![TypeErr::new(id.pos, "Expected class name")]),
}
}

pub fn all_pure(self, pure: bool) -> TypeResult<Self> {
let functions = self.functions.iter().map(|f| f.clone().pure(pure)).collect();
Ok(GenericClass { functions, ..self })
Expand Down
29 changes: 28 additions & 1 deletion src/check/context/generic.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::collections::HashSet;
use std::convert::TryFrom;

use itertools::EitherOrBoth::{Both, Left, Right};
use itertools::Itertools;

use crate::check::context::clss::generic::GenericClass;
use crate::check::context::field::generic::{GenericField, GenericFields};
use crate::check::context::function::generic::GenericFunction;
use crate::check::result::{TypeErr, TypeResult};
use crate::parse::ast::{AST, Node};
use crate::parse::ast::{AST, Node, OptAST};

pub fn generics(
files: &[AST],
Expand All @@ -30,6 +33,10 @@ pub fn generics(
fields.insert(ty.clone());
});
}
Node::Import { from, import, alias } =>
from_import(from, import, alias)?.into_iter().for_each(|t| {
types.insert(t);
}),
_ => {}
}
}
Expand All @@ -40,3 +47,23 @@ pub fn generics(

Ok((types, fields, functions))
}

/// From import.
///
/// A more elaborate import system will extract the signature of the class.
fn from_import(_from: &OptAST, import: &[AST], alias: &[AST]) -> TypeResult<Vec<GenericClass>> {
let (mut classes, mut errs) = (vec![], vec![]);
for pair in import.iter().zip_longest(alias) {
match pair {
Left(import) => classes.push(GenericClass::try_from_id(import)?),
Both(_, alias) => classes.push(GenericClass::try_from_id(alias)?),
Right(alias) => {
let msg = format!("alias with no matching import: {}", alias.node);
errs.push(TypeErr::new(alias.pos, &msg));
}
}
}

if !errs.is_empty() { return Err(errs); }
Ok(classes)
}
39 changes: 39 additions & 0 deletions src/check/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ mod tests {
use crate::check::name::string_name::StringName;
use crate::check::result::TypeResult;
use crate::common::position::Position;
use crate::parse::parse;

#[test]
pub fn lookup_custom_list_type() -> TypeResult<()> {
Expand Down Expand Up @@ -156,4 +157,42 @@ mod tests {
context.class(&StringName::from("None"), Position::default()).unwrap();
context.class(&StringName::from("Exception"), Position::default()).unwrap();
}

#[test]
pub fn test_import_parse() {
let file = parse("import IPv4Address").unwrap();
let context = Context::try_from(vec![*file.clone()].as_slice()).unwrap();

context.class(&StringName::from("IPv4Address"), Position::default()).unwrap();
}

#[test]
pub fn test_import_as_parse() {
let file = parse("import IPv4Address as Other").unwrap();
let context = Context::try_from(vec![*file.clone()].as_slice()).unwrap();

context.class(&StringName::from("Other"), Position::default()).unwrap();
}

#[test]
pub fn test_import_as_too_many_parse() {
let file = parse("import IPv4Address as Other, Other2").unwrap();
Context::try_from(vec![*file.clone()].as_slice()).unwrap_err();
}

#[test]
pub fn test_from_import_parse() {
let file = parse("from ipaddress import IPv4Address").unwrap();
let context = Context::try_from(vec![*file.clone()].as_slice()).unwrap();

context.class(&StringName::from("IPv4Address"), Position::default()).unwrap();
}

#[test]
pub fn test_from_import_as_parse() {
let file = parse("from ipaddress import IPv4Address as Other").unwrap();
let context = Context::try_from(vec![*file.clone()].as_slice()).unwrap();

context.class(&StringName::from("Other"), Position::default()).unwrap();
}
}

0 comments on commit 708b67c

Please sign in to comment.