From c1acd63c8e4ea0cb0517a2ec352567b369056a23 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 14 Aug 2016 18:57:08 +1000 Subject: [PATCH] Move some types out of the ast module --- base/src/ast.rs | 92 +------------------------------------- base/src/error.rs | 3 +- base/src/pos.rs | 94 ++++++++++++++++++++++++++++++++++++++- check/src/completion.rs | 5 ++- check/src/rename.rs | 5 ++- check/src/typecheck.rs | 31 ++++++------- check/tests/completion.rs | 4 +- check/tests/fail.rs | 6 +-- check/tests/pass.rs | 8 ++-- parser/src/lib.rs | 2 +- parser/tests/basic.rs | 6 +-- src/import.rs | 4 +- 12 files changed, 135 insertions(+), 125 deletions(-) diff --git a/base/src/ast.rs b/base/src/ast.rs index bfacc62a1d..3fa0184f33 100644 --- a/base/src/ast.rs +++ b/base/src/ast.rs @@ -1,9 +1,9 @@ //! Module containing the types which make up `gluon`'s AST (Abstract Syntax Tree) -use std::cmp::Ordering; + use std::fmt; use std::ops::Deref; -use pos::{BytePos, CharPos}; +use pos::{CharPos, Located, Span}; use symbol::Symbol; use types::{self, Alias, AliasData, Kind, Type, TypeEnv, TypeVariable}; @@ -169,94 +169,6 @@ impl IdentEnv for TcIdentEnv } } -/// Representation of a location in a source file -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)] -pub struct Location { - pub row: u32, - pub column: CharPos, - pub absolute: BytePos, -} - -impl Location { - fn line_offset(mut self, offset: CharPos) -> Location { - self.column += offset; - self - } -} - -impl fmt::Display for Location { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Line: {}, Column: {}", self.row, self.column) - } -} - -/// Struct which represents a span in a source file -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Span { - pub start: Location, - pub end: Location, -} - -impl Span { - pub fn containment(&self, location: &Location) -> Ordering { - use std::cmp::Ordering::*; - match (location.cmp(&self.start), location.cmp(&self.end)) { - (Equal, _) | (Greater, Less) => Equal, - (Less, _) => Less, - (_, Equal) | (_, Greater) => Greater, - } - } - pub fn containment_exclusive(&self, location: &Location) -> Ordering { - if self.end == *location { - Ordering::Greater - } else { - self.containment(location) - } - } -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct Spanned { - pub span: Span, - pub value: T, -} - -impl fmt::Display for Spanned { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.span.start, self.value) - } -} - -#[derive(Clone, Debug)] -pub struct Located { - pub location: Location, - pub value: T, -} -impl PartialEq for Located { - fn eq(&self, other: &Located) -> bool { - self.value == other.value - } -} -impl Deref for Located { - type Target = T; - fn deref(&self) -> &T { - &self.value - } -} - -impl fmt::Display for Located { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.location, self.value) - } -} - -pub fn located(location: Location, value: T) -> Located { - Located { - location: location, - value: value, - } -} - #[derive(Clone, PartialEq, Debug)] pub enum LiteralEnum { Byte(u8), diff --git a/base/src/error.rs b/base/src/error.rs index 28f62ed702..2f610a4b6a 100644 --- a/base/src/error.rs +++ b/base/src/error.rs @@ -1,10 +1,11 @@ //! Module containing a few common error wrappers which allows more information to be saved for //! later display to the user + use std::any::Any; use std::error::Error as StdError; use std::fmt; -use ast::Spanned; +use pos::Spanned; /// An error type which can represent multiple errors. #[derive(Debug, PartialEq)] diff --git a/base/src/pos.rs b/base/src/pos.rs index d24524fc53..6827c81423 100644 --- a/base/src/pos.rs +++ b/base/src/pos.rs @@ -2,8 +2,9 @@ //! //! [libsyntax_pos]: https://github.com/rust-lang/rust/blob/ae774103501337ed63b42b673c6c4fdbf369e80e/src/libsyntax_pos/lib.rs +use std::cmp::Ordering; use std::fmt; -use std::ops::{Add, AddAssign, Sub, SubAssign}; +use std::ops::{Add, AddAssign, Deref, Sub, SubAssign}; /// A byte offset in a source string #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] @@ -104,3 +105,94 @@ impl fmt::Display for CharPos { self.0.fmt(f) } } + +/// A location in a source file +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)] +pub struct Location { + pub row: u32, + pub column: CharPos, + pub absolute: BytePos, +} + +impl Location { + pub fn line_offset(mut self, offset: CharPos) -> Location { + self.column += offset; + self + } +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Line: {}, Column: {}", self.row, self.column) + } +} + +/// A span between two locations in a source file +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Span { + pub start: Location, + pub end: Location, +} + +impl Span { + pub fn containment(&self, location: &Location) -> Ordering { + use std::cmp::Ordering::*; + match (location.cmp(&self.start), location.cmp(&self.end)) { + (Equal, _) | (Greater, Less) => Equal, + (Less, _) => Less, + (_, Equal) | (_, Greater) => Greater, + } + } + + pub fn containment_exclusive(&self, location: &Location) -> Ordering { + if self.end == *location { + Ordering::Greater + } else { + self.containment(location) + } + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Spanned { + pub span: Span, + pub value: T, +} + +impl fmt::Display for Spanned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", self.span.start, self.value) + } +} + +#[derive(Clone, Debug)] +pub struct Located { + pub location: Location, + pub value: T, +} + +impl PartialEq for Located { + fn eq(&self, other: &Located) -> bool { + self.value == other.value + } +} + +impl Deref for Located { + type Target = T; + fn deref(&self) -> &T { + &self.value + } +} + +impl fmt::Display for Located { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", self.location, self.value) + } +} + +pub fn located(location: Location, value: T) -> Located { + Located { + location: location, + value: value, + } +} diff --git a/check/src/completion.rs b/check/src/completion.rs index 8c00e21289..dfb4db71c7 100644 --- a/check/src/completion.rs +++ b/check/src/completion.rs @@ -3,8 +3,9 @@ use std::iter::once; use std::cmp::Ordering; -use base::ast::{self, DisplayEnv, Expr, LExpr, Location, LPattern, Pattern, TcIdent, Typed}; +use base::ast::{DisplayEnv, Expr, LExpr, LPattern, Pattern, TcIdent, Typed}; use base::instantiate; +use base::pos::{Location, Span}; use base::scoped_map::ScopedMap; use base::symbol::Symbol; use base::types::{TcType, Type, TypeEnv}; @@ -111,7 +112,7 @@ struct FindVisitor<'a, F> { impl<'a, F> FindVisitor<'a, F> { fn select_spanned<'e, I, S, T>(&self, iter: I, mut span: S) -> (bool, Option<&'e T>) where I: IntoIterator, - S: FnMut(&T) -> ast::Span + S: FnMut(&T) -> Span { let mut iter = iter.into_iter().peekable(); let mut prev = None; diff --git a/check/src/rename.rs b/check/src/rename.rs index 7a63a46ed9..49b8878d9a 100644 --- a/check/src/rename.rs +++ b/check/src/rename.rs @@ -1,6 +1,7 @@ use std::fmt; -use base::ast::{self, DisplayEnv, Expr, LExpr, Location, MutVisitor, Spanned, Typed}; +use base::ast::{self, DisplayEnv, Expr, LExpr, MutVisitor, Typed}; +use base::pos::{self, Location, Spanned}; use base::error::Errors; use base::fnv::FnvMap; use base::scoped_map::ScopedMap; @@ -213,7 +214,7 @@ pub fn rename(symbols: &mut SymbolModule, None => { if let Some(new_id) = try!(self.rename(id, &field.typ)) { debug!("Rename record field {} = {}", id, new_id); - *maybe_expr = Some(ast::located(expr.location, + *maybe_expr = Some(pos::located(expr.location, Expr::Identifier(TcIdent { name: new_id, typ: field.typ.clone(), diff --git a/check/src/typecheck.rs b/check/src/typecheck.rs index 57f9928154..470ae9e70f 100644 --- a/check/src/typecheck.rs +++ b/check/src/typecheck.rs @@ -6,11 +6,12 @@ use std::mem; use base::scoped_map::ScopedMap; use base::ast::{self, Typed, DisplayEnv, MutVisitor}; -use base::types::{self, RcKind, Type, Generic, Kind}; use base::error::Errors; +use base::instantiate::{self, Instantiator}; +use base::pos::{Span, Spanned}; use base::symbol::{Symbol, SymbolRef, SymbolModule, Symbols}; +use base::types::{self, RcKind, Type, Generic, Kind}; use base::types::{KindEnv, TypeEnv, PrimitiveEnv, TcIdent, Alias, AliasData, TcType, TypeVariable}; -use base::instantiate::{self, Instantiator}; use kindcheck::{self, KindCheck}; use substitution::Substitution; use unify::Error as UnifyError; @@ -207,13 +208,13 @@ pub struct Typecheck<'a> { original_symbols: ScopedMap, subs: Substitution, inst: Instantiator, - errors: Errors>>, + errors: Errors>>, /// Type variables `let test: a -> b` (`a` and `b`) type_variables: ScopedMap, } /// Error returned when unsuccessfully typechecking an expression -pub type Error = Errors>>; +pub type Error = Errors>>; impl<'a> Typecheck<'a> { /// Create a new typechecker which typechecks expressions in `module` @@ -237,8 +238,8 @@ impl<'a> Typecheck<'a> { } } - fn error(&mut self, span: ast::Span, error: TypeError) -> TcType { - self.errors.error(ast::Spanned { + fn error(&mut self, span: Span, error: TypeError) -> TcType { + self.errors.error(Spanned { span: span, value: error, }); @@ -249,7 +250,7 @@ impl<'a> Typecheck<'a> { self.environment.get_bool().clone() } - fn find_at(&mut self, span: ast::Span, id: &Symbol) -> TcType { + fn find_at(&mut self, span: Span, id: &Symbol) -> TcType { match self.find(id) { Ok(typ) => typ, Err(err) => self.error(span, err), @@ -402,8 +403,8 @@ impl<'a> Typecheck<'a> { Ok(typ) } Err(errors) => { - for ast::Spanned { span, value } in errors.errors { - self.errors.error(ast::Spanned { + for Spanned { span, value } in errors.errors { + self.errors.error(Spanned { span: span, value: value.into(), }); @@ -444,7 +445,7 @@ impl<'a> Typecheck<'a> { } Err(err) => { returned_type = self.subs.new_var(); - self.errors.error(ast::Spanned { + self.errors.error(Spanned { span: expr.span(&ast::TcIdentEnvWrapper(&self.symbols)), value: err, }); @@ -984,7 +985,7 @@ impl<'a> Typecheck<'a> { // Finally insert the declared types into the global scope for bind in bindings { if self.environment.stack_types.get(&bind.name).is_some() { - self.errors.error(ast::Spanned { + self.errors.error(Spanned { span: expr.span(&ast::TcIdentEnvWrapper(&self.symbols)), value: DuplicateTypeDefinition(bind.name.clone()), }); @@ -1226,7 +1227,7 @@ impl<'a> Typecheck<'a> { } fn merge_signature(&mut self, - span: ast::Span, + span: Span, level: u32, expected: &TcType, mut actual: TcType) @@ -1245,7 +1246,7 @@ impl<'a> Typecheck<'a> { actual = self.subs.set_type(actual); let err = TypeError::Unification(expected, actual, apply_subs(&self.subs, errors.errors)); - self.errors.error(ast::Spanned { + self.errors.error(Spanned { span: span, value: err, }); @@ -1254,11 +1255,11 @@ impl<'a> Typecheck<'a> { } } - fn unify_span(&mut self, span: ast::Span, expected: &TcType, actual: TcType) -> TcType { + fn unify_span(&mut self, span: Span, expected: &TcType, actual: TcType) -> TcType { match self.unify(expected, actual) { Ok(typ) => typ, Err(err) => { - self.errors.error(ast::Spanned { + self.errors.error(Spanned { span: span, value: err, }); diff --git a/check/tests/completion.rs b/check/tests/completion.rs index 8b6ec02710..bfdf41c19e 100644 --- a/check/tests/completion.rs +++ b/check/tests/completion.rs @@ -4,8 +4,8 @@ extern crate gluon_base as base; extern crate gluon_parser as parser; extern crate gluon_check as check; -use base::ast::{self, Location}; -use base::pos::{BytePos, CharPos}; +use base::ast; +use base::pos::{BytePos, CharPos, Location}; use base::types::{Type, TcType}; use check::completion; diff --git a/check/tests/fail.rs b/check/tests/fail.rs index 7ccd9fe725..31cc4f63a3 100644 --- a/check/tests/fail.rs +++ b/check/tests/fail.rs @@ -4,7 +4,7 @@ extern crate gluon_base as base; extern crate gluon_parser as parser; extern crate gluon_check as check; -use base::ast; +use base::pos::Spanned; use base::types; mod support; @@ -25,7 +25,7 @@ macro_rules! assert_err { let mut iter = err.errors.iter(); $( match iter.next() { - Some(&ast::Spanned { value: $id, .. }) => (), + Some(&Spanned { value: $id, .. }) => (), _ => assert!(false, "Found errors:\n{}\nbut expected {}", err, stringify!($id)), } @@ -52,7 +52,7 @@ macro_rules! assert_unify_err { Err(err) => { for err in err.errors.iter() { match *err { - ast::Spanned { value: Unification(_, _, ref errors), .. } => { + Spanned { value: Unification(_, _, ref errors), .. } => { let mut iter = errors.iter(); $( match iter.next() { diff --git a/check/tests/pass.rs b/check/tests/pass.rs index 9b7a86aae3..bee828ae28 100644 --- a/check/tests/pass.rs +++ b/check/tests/pass.rs @@ -5,7 +5,7 @@ extern crate gluon_parser as parser; extern crate gluon_check as check; use base::ast::{self, Expr, Pattern, Typed}; -use base::pos::{BytePos, CharPos}; +use base::pos::{BytePos, CharPos, Location, Span}; use base::types::{self, Field, Generic, Kind, Type}; mod support; @@ -720,13 +720,13 @@ in f "123" let err = result.unwrap_err(); assert_eq!(err.errors.len(), 1); assert_eq!(err.errors[0].span, - ast::Span { - start: ast::Location { + Span { + start: Location { row: 3, column: CharPos(6), absolute: BytePos(0), }, - end: ast::Location { + end: Location { row: 3, column: CharPos(11), absolute: BytePos(0), diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 3aadc3e791..8b10912910 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -17,7 +17,7 @@ use std::rc::Rc; use base::ast; use base::ast::*; use base::error::Errors; -use base::pos::{BytePos, CharPos}; +use base::pos::{BytePos, CharPos, Located, Location, located}; use base::types::{Type, Generic, Alias, Field, Kind, TypeVariable}; use base::symbol::{Name, Symbol, SymbolModule}; diff --git a/parser/tests/basic.rs b/parser/tests/basic.rs index 2dd972b138..01681f47bf 100644 --- a/parser/tests/basic.rs +++ b/parser/tests/basic.rs @@ -4,10 +4,10 @@ extern crate env_logger; #[macro_use] extern crate log; -use base::ast::*; use base::ast; +use base::ast::*; use base::error::Errors; -use base::pos::{BytePos, CharPos}; +use base::pos::{self, BytePos, CharPos, Located, Location, Span}; use base::types::{Type, Generic, Alias, Field, Kind}; use parser::{parse_string, Error}; @@ -32,7 +32,7 @@ fn no_loc(x: T) -> Located { absolute: BytePos(u32::max_value()), }; - located(max_loc, x) + pos::located(max_loc, x) } fn binop(l: PExpr, s: &str, r: PExpr) -> PExpr { diff --git a/src/import.rs b/src/import.rs index 6d52076b52..3cb7f77dae 100644 --- a/src/import.rs +++ b/src/import.rs @@ -1,4 +1,5 @@ //! Implementation of the `import` macro. + use std::any::Any; use std::sync::{Arc, RwLock, Mutex}; use std::fs::File; @@ -8,6 +9,7 @@ use std::path::{Path, PathBuf}; use base::ast; use base::metadata::Metadata; +use base::pos; use base::symbol::Symbol; use vm::macros::{Macro, Error as MacroError}; use vm::thread::{Thread, ThreadInternal}; @@ -163,7 +165,7 @@ impl Macro for Import try!(self.importer.import(vm, &modulename, file_contents)); } // FIXME Does not handle shadowing - Ok(ast::located(arguments[0].location, + Ok(pos::located(arguments[0].location, ast::Expr::Identifier(TcIdent::new(name)))) } _ => return Err(Error::String("Expected a string literal to import".into()).into()),