Skip to content

Commit

Permalink
Make it less painful to copy ranges
Browse files Browse the repository at this point in the history
This adds a duplicate `Range` type that implements `Copy`, unlike `std::ops::Range`.
  • Loading branch information
brendanzab committed Nov 15, 2020
1 parent 688d7cb commit b871243
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 219 deletions.
34 changes: 25 additions & 9 deletions pikelet/src/lang.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Intermediate languages of the Pikelet compiler.

use std::ops::Range;

pub mod surface;
// 🠃
pub mod core;
Expand All @@ -12,28 +10,46 @@ pub mod cc;
// 🠃
// ...

/// A range of source code.
#[derive(Debug, Copy, Clone)]
pub struct Range {
pub start: usize,
pub end: usize,
}

impl Into<std::ops::Range<usize>> for Range {
fn into(self) -> std::ops::Range<usize> {
self.start..self.end
}
}

impl From<std::ops::Range<usize>> for Range {
fn from(src: std::ops::Range<usize>) -> Range {
Range {
start: src.start,
end: src.end,
}
}
}

/// Data that covers some range of source code.
#[derive(Debug, Clone)]
pub struct Ranged<Data> {
pub range: Range<usize>,
pub range: Range,
pub data: Data,
}

impl<Data> Ranged<Data> {
pub fn new(range: Range<usize>, data: Data) -> Ranged<Data> {
pub fn new(range: Range, data: Data) -> Ranged<Data> {
Ranged { range, data }
}

pub fn range(&self) -> Range<usize> {
self.range.clone()
}
}

impl<Data> From<Data> for Ranged<Data> {
#![allow(clippy::reversed_empty_ranges)]
fn from(data: Data) -> Ranged<Data> {
// TODO: Use a better marker for data that does not originate from to a
// specific source location.
Ranged::new(0..0, data)
Ranged::new(Range::from(0..0), data)
}
}
4 changes: 2 additions & 2 deletions pikelet/src/lang/surface/grammar.lalrpop
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::lang::Ranged;
use crate::lang::{Range, Ranged};
use crate::lang::surface::{Term, TermData, TypeEntry, TermEntry};
use crate::lang::surface::lexer::Token;
use crate::reporting::LexerError;
Expand Down Expand Up @@ -120,5 +120,5 @@ Name: String = {

#[inline]
Ranged<T>: Ranged<T> = {
<start: @L> <data: T> <end: @R> => Ranged::new(start..end, data),
<start: @L> <data: T> <end: @R> => Ranged::new(Range::from(start..end), data),
};
4 changes: 3 additions & 1 deletion pikelet/src/lang/surface/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ pub fn tokens<'a>(
Token::lexer(source)
.spanned()
.map(|(token, range)| match token {
Token::Error => Err(LexerError::InvalidToken { range }),
Token::Error => Err(LexerError::InvalidToken {
range: range.into(),
}),
token => Ok((range.start, token, range.end)),
})
}
Expand Down
27 changes: 11 additions & 16 deletions pikelet/src/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use crossbeam_channel::Sender;
use logos::Logos;
use num_traits::{Float, PrimInt, Signed, Unsigned};
use std::ops::Range;

use crate::lang::Range;
use crate::reporting::LiteralParseMessage::*;
use crate::reporting::Message;

Expand Down Expand Up @@ -193,14 +193,14 @@ enum AsciiEscape<'source> {

/// Literal parser state.
pub struct State<'source, 'messages> {
range: Range<usize>,
range: Range,
source: &'source str,
message_tx: &'messages Sender<Message>,
}

impl<'source, 'messages> State<'source, 'messages> {
pub fn new(
range: Range<usize>,
range: Range,
source: &'source str,
message_tx: &'messages Sender<Message>,
) -> State<'source, 'messages> {
Expand All @@ -217,18 +217,13 @@ impl<'source, 'messages> State<'source, 'messages> {
None
}

/// The range of the entire literal.
fn range(&self) -> Range<usize> {
self.range.clone()
}

/// Get the file-relative range of the current token.
fn token_range<Token>(&self, lexer: &logos::Lexer<'source, Token>) -> Range<usize>
fn token_range<Token>(&self, lexer: &logos::Lexer<'source, Token>) -> Range
where
Token: Logos<'source>,
{
let span = lexer.span();
(self.range.start + span.start)..(self.range.start + span.end)
Range::from((self.range.start + span.start)..(self.range.start + span.end))
}

/// Parse a numeric literal into an unsigned integer.
Expand All @@ -242,7 +237,7 @@ impl<'source, 'messages> State<'source, 'messages> {

let (base, start_digit) = match self.expect_numeric_literal_start(&mut lexer)? {
(Sign::Positive, base, start_digit) => (base, start_digit),
(Sign::Negative, _, _) => return self.report(NegativeUnsignedInteger(self.range())),
(Sign::Negative, _, _) => return self.report(NegativeUnsignedInteger(self.range)),
};

let mut lexer = lexer.morph();
Expand Down Expand Up @@ -420,7 +415,7 @@ impl<'source, 'messages> State<'source, 'messages> {

Some(float)
} else {
self.report(UnsupportedFloatLiteralBase(self.range(), base))
self.report(UnsupportedFloatLiteralBase(self.range, base))
}
}

Expand Down Expand Up @@ -454,7 +449,7 @@ impl<'source, 'messages> State<'source, 'messages> {
Sign::Positive => T::checked_add(&place_shifted, &T::from(digit).unwrap()),
Sign::Negative => T::checked_sub(&place_shifted, &T::from(digit).unwrap()),
})
.or_else(|| self.report(LiteralOutOfRange(self.range())))
.or_else(|| self.report(LiteralOutOfRange(self.range)))
}

/// Parse a quoted literal into a Unicode encoded character.
Expand All @@ -479,7 +474,7 @@ impl<'source, 'messages> State<'source, 'messages> {
for ch in text.chars() {
match character {
None => character = Some(ch),
Some(_) => return self.report(OverlongCharLiteral(self.range())),
Some(_) => return self.report(OverlongCharLiteral(self.range)),
}
}
}
Expand All @@ -499,7 +494,7 @@ impl<'source, 'messages> State<'source, 'messages> {
},
QuotedText::End(quote) => match character {
None => character = Some(quote.to_char()),
Some(_) => return self.report(OverlongCharLiteral(self.range())),
Some(_) => return self.report(OverlongCharLiteral(self.range)),
},

QuotedText::Error => return self.report(InvalidToken(self.token_range(&lexer))),
Expand All @@ -508,7 +503,7 @@ impl<'source, 'messages> State<'source, 'messages> {

match character {
Some(ch) => Some(ch),
None => self.report(EmptyCharLiteral(self.range())),
None => self.report(EmptyCharLiteral(self.range)),
}
}

Expand Down
Loading

0 comments on commit b871243

Please sign in to comment.