Merge branch 'trunk' of github.com:rtfeldman/roc into editor-comments

This commit is contained in:
Anton-4 2022-01-01 11:10:54 +01:00
commit f941e30b86
271 changed files with 15287 additions and 8370 deletions

View file

@ -1,12 +1,70 @@
use std::fmt::Debug;
use crate::header::{AppHeader, ImportsEntry, InterfaceHeader, PlatformHeader, TypedIdent};
use crate::header::{AppHeader, InterfaceHeader, PlatformHeader};
use crate::ident::Ident;
use bumpalo::collections::{String, Vec};
use bumpalo::Bump;
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
use roc_region::all::{Loc, Position, Region};
#[derive(Debug)]
pub struct Spaces<'a, T> {
pub before: &'a [CommentOrNewline<'a>],
pub item: T,
pub after: &'a [CommentOrNewline<'a>],
}
#[derive(Copy, Clone, PartialEq)]
pub enum Spaced<'a, T> {
Item(T),
// Spaces
SpaceBefore(&'a Spaced<'a, T>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a Spaced<'a, T>, &'a [CommentOrNewline<'a>]),
}
impl<'a, T: Debug> Debug for Spaced<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Item(item) => item.fmt(f),
Self::SpaceBefore(item, space) => f
.debug_tuple("SpaceBefore")
.field(item)
.field(space)
.finish(),
Self::SpaceAfter(item, space) => f
.debug_tuple("SpaceAfter")
.field(item)
.field(space)
.finish(),
}
}
}
pub trait ExtractSpaces<'a>: Sized + Copy {
type Item;
fn extract_spaces(&self) -> Spaces<'a, Self::Item>;
}
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for &'a T {
type Item = T::Item;
fn extract_spaces(&self) -> Spaces<'a, Self::Item> {
(*self).extract_spaces()
}
}
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for Loc<T> {
type Item = T::Item;
fn extract_spaces(&self) -> Spaces<'a, Self::Item> {
let spaces = self.value.extract_spaces();
Spaces {
before: spaces.before,
item: spaces.item,
after: spaces.after,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Module<'a> {
Interface { header: InterfaceHeader<'a> },
@ -167,6 +225,12 @@ pub struct PrecedenceConflict<'a> {
pub expr: &'a Loc<Expr<'a>>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AliasHeader<'a> {
pub name: Loc<&'a str>,
pub vars: &'a [Loc<Pattern<'a>>],
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Def<'a> {
// TODO in canonicalization, validate the pattern; only certain patterns
@ -178,8 +242,7 @@ pub enum Def<'a> {
///
/// Foo : Bar Baz
Alias {
name: Loc<&'a str>,
vars: &'a [Loc<Pattern<'a>>],
header: AliasHeader<'a>,
ann: Loc<TypeAnnotation<'a>>,
},
@ -207,6 +270,17 @@ pub enum Def<'a> {
NotYetImplemented(&'static str),
}
impl<'a> Def<'a> {
pub fn unroll_spaces_before(&self) -> (&'a [CommentOrNewline<'a>], &Def) {
let (spaces, def): (&'a [_], &Def) = match self {
Def::SpaceBefore(def, spaces) => (spaces, def),
def => (&[], def),
};
debug_assert!(!matches!(def, Def::SpaceBefore(_, _)));
(spaces, def)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TypeAnnotation<'a> {
/// A function. The types of its arguments, then the type of its return value.
@ -222,7 +296,7 @@ pub enum TypeAnnotation<'a> {
As(
&'a Loc<TypeAnnotation<'a>>,
&'a [CommentOrNewline<'a>],
&'a Loc<TypeAnnotation<'a>>,
AliasHeader<'a>,
),
Record {
@ -341,7 +415,7 @@ pub enum Pattern<'a> {
PrivateTag(&'a str),
Apply(&'a Loc<Pattern<'a>>, &'a [Loc<Pattern<'a>>]),
/// This is Loc<Pattern> rather than Loc<str> so we can record comments
/// This is Located<Pattern> rather than Located<str> so we can record comments
/// around the destructured names, e.g. { x ### x does stuff ###, y }
/// In practice, these patterns will always be Identifier
RecordDestructure(Collection<'a, Loc<Pattern<'a>>>),
@ -649,6 +723,15 @@ pub trait Spaceable<'a> {
}
}
impl<'a, T> Spaceable<'a> for Spaced<'a, T> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
Spaced::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
Spaced::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for Expr<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
Expr::SpaceBefore(self, spaces)
@ -676,24 +759,6 @@ impl<'a> Spaceable<'a> for TypeAnnotation<'a> {
}
}
impl<'a> Spaceable<'a> for ImportsEntry<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ImportsEntry::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
ImportsEntry::SpaceAfter(self, spaces)
}
}
impl<'a> Spaceable<'a> for TypedIdent<'a> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
TypedIdent::SpaceBefore(self, spaces)
}
fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
TypedIdent::SpaceAfter(self, spaces)
}
}
impl<'a, Val> Spaceable<'a> for AssignedField<'a, Val> {
fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self {
AssignedField::SpaceBefore(self, spaces)
@ -735,4 +800,122 @@ impl<'a> Expr<'a> {
value: self,
}
}
pub fn is_tag(&self) -> bool {
matches!(self, Expr::GlobalTag(_) | Expr::PrivateTag(_))
}
}
macro_rules! impl_extract_spaces {
($t:ident $(< $($generic_args:ident),* >)?) => {
impl<'a, $($($generic_args: Copy),*)?> ExtractSpaces<'a> for $t<'a, $($($generic_args),*)?> {
type Item = Self;
fn extract_spaces(&self) -> Spaces<'a, Self::Item> {
match self {
$t::SpaceBefore(item, before) => {
match item {
$t::SpaceBefore(_, _) => todo!(),
$t::SpaceAfter(item, after) => {
Spaces {
before,
item: **item,
after,
}
}
_ => {
Spaces {
before,
item: **item,
after: &[],
}
}
}
},
$t::SpaceAfter(item, after) => {
match item {
$t::SpaceBefore(item, before) => {
Spaces {
before,
item: **item,
after,
}
}
$t::SpaceAfter(_, _) => todo!(),
_ => {
Spaces {
before: &[],
item: **item,
after,
}
}
}
},
_ => {
Spaces {
before: &[],
item: *self,
after: &[],
}
}
}
}
}
};
}
impl_extract_spaces!(Expr);
impl_extract_spaces!(Tag);
impl_extract_spaces!(AssignedField<T>);
impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
type Item = T;
fn extract_spaces(&self) -> Spaces<'a, T> {
match self {
Spaced::SpaceBefore(item, before) => match item {
Spaced::SpaceBefore(_, _) => todo!(),
Spaced::SpaceAfter(item, after) => {
if let Spaced::Item(item) = item {
Spaces {
before,
item: *item,
after,
}
} else {
todo!();
}
}
Spaced::Item(item) => Spaces {
before,
item: *item,
after: &[],
},
},
Spaced::SpaceAfter(item, after) => match item {
Spaced::SpaceBefore(item, before) => {
if let Spaced::Item(item) = item {
Spaces {
before,
item: *item,
after,
}
} else {
todo!();
}
}
Spaced::SpaceAfter(_, _) => todo!(),
Spaced::Item(item) => Spaces {
before: &[],
item: *item,
after,
},
},
Spaced::Item(item) => Spaces {
before: &[],
item: *item,
after: &[],
},
}
}
}