Skip to content

Commit

Permalink
Allow closing brackets to be further dedented
Browse files Browse the repository at this point in the history
Previously, we would insert a line break before such a closing brackets
according to the rules. However, I'd like to be able to place my closing
bracket at the same indentation level as the respective opening one.

See the updated UI tests for example.

The current approach is quite liberal and careless. In the future we
should probably restrict this a bit, e.g. forbidding closing brackets
to be further indented than the respective opening one.
  • Loading branch information
fmease committed Aug 4, 2023
1 parent fa19c89 commit d4149d2
Show file tree
Hide file tree
Showing 18 changed files with 78 additions and 28 deletions.
26 changes: 22 additions & 4 deletions compiler/lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,13 @@ impl<'a> Lexer<'a> {
.map_or(false, |token| token.bare.introduces_indented_section());

// Squash consecutive line breaks into a single one.
// This leads to more legible and fewer diagnostics later in the parser in case the
// line break wasn't expected. Further, it might lead to less churn in the parser.
self.take_while(|character| character == '\n');
// Tentatively register the line break. If certain conditions are met
// later on (*), we will remove it again.
// Tentatively register the line break.
// If certain conditions are met later on (*), we will remove it again.
self.add(LineBreak);
let mut has_removed_line_break = false;

self.local_span = self
.index()
Expand All @@ -313,7 +316,10 @@ impl<'a> Lexer<'a> {
let mut spaces = Spaces(0);
self.take_while_with(|character| character == ' ', || spaces.0 += 1);

// If the line is empty ignore it. This is important for indented comments.
// If the line is empty ignore it. While most places in the parser can deal with
// “empty declarations”, in the future (once `line_is_empty` can detect comments
// as well) we might want to simplify the parser by throwing away the special
// handling (i.e. skipping) of empty lines.
if self.line_is_empty() {
spaces = self.indentation;
}
Expand All @@ -336,6 +342,7 @@ impl<'a> Lexer<'a> {
if change == Ordering::Greater {
// (*) Remove the line break again.
self.tokens.pop();
has_removed_line_break = true;
self.add(BareToken::Indentation);
self.sections.enter(Section::Indented {
brackets: self.brackets.stack.len(),
Expand All @@ -355,6 +362,7 @@ impl<'a> Lexer<'a> {
{
// (*) Remove the line break again.
self.tokens.pop();
has_removed_line_break = true;
}

if change == Ordering::Greater {
Expand All @@ -365,11 +373,12 @@ impl<'a> Lexer<'a> {
if change == Ordering::Less {
// Remove syntactically legal but superfluous line breaks that
// come before dedendentation (which also act as terminators).
// @Question is this still reachable???
if self.sections.current_continued().0.is_indented()
&& let Some(Spanned!(_, BareToken::LineBreak)) = self.tokens.last()
{
// (*) Remove the line break again.
self.tokens.pop();
has_removed_line_break = true;
}

for _ in 0..indentation.0 {
Expand All @@ -384,6 +393,15 @@ impl<'a> Lexer<'a> {
}

self.indentation = spaces;

// @Task only remove the line break if the indentation of the closing bracket is
// greater or equal to the one of the corresponding opening bracket.
// @Note actually it would be even better if we could emit a nice diagnostic for
// closing brackets that are dedented too far.
if let Some(')' | ']' | '}') = self.peek() && !has_removed_line_break {
// (*) Remove the line break again.
self.tokens.pop();
}
}

fn line_is_empty(&mut self) -> bool {
Expand Down
23 changes: 20 additions & 3 deletions compiler/lexer/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ of
}

#[test]
fn no_superfluous_virtual_semicolon_before_virtual_curly_bracket_with_continued_section() {
fn no_superfluous_line_break_before_dedentation_token_with_continued_section() {
assert_lex_eq!(
"\
of
Expand All @@ -627,7 +627,7 @@ of
}

#[test]
fn empty_indented_section_does_not_create_virtual_curly_brackets() {
fn empty_indented_section_does_not_create_indentation_tokens() {
assert_lex_eq!(
"\
of
Expand Down Expand Up @@ -694,7 +694,6 @@ fn round_bracket_closes_indented_section() {
Token::new(span(14, 16), Of),
Token::new(span(17, 21), Indentation),
Token::new(span(21, 23), Word("fo".into())),
Token::new(span(23, 24), LineBreak),
// @Question better span?
Token::new(span(28, 29), Dedentation),
Token::new(span(28, 29), ClosingRoundBracket),
Expand Down Expand Up @@ -777,6 +776,24 @@ fn brackets_reset_indentation() {
)
}

#[test]
fn dedented_closing_bracket_does_not_create_line_break() {
assert_lex_eq!(
"\
hook = (
element
)",
vec![
Token::new(span(1, 5), Word("hook".into())),
Token::new(span(6, 7), Equals),
Token::new(span(8, 9), OpeningRoundBracket),
Token::new(span(14, 21), Word("element".into())),
Token::new(span(22, 23), ClosingRoundBracket),
Token::new(span(23, 23), EndOfInput),
]
);
}

#[test]
fn indentation_at_start_of_input() {
assert_lex_eq!(
Expand Down
8 changes: 5 additions & 3 deletions library/core/source/library/ordering.lushui
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
;; Types and functions related to comparing and ordering.
module

use topmost.(
unit.(unit, Unit, Thunk, force),
int.Int,
)

@public
data Ordering of
less
Expand All @@ -17,9 +22,6 @@ invert (o: Ordering): Ordering =
equal => equal
greater => less

use topmost.unit.(unit, Unit, Thunk, force)
use topmost.int.Int

;;; @Task uncomment once `@lazy` is implemented
;;; @public
;;; then (o: Ordering) @lazy (p: Thunk Ordering): Ordering =
Expand Down
6 changes: 4 additions & 2 deletions library/core/source/library/vector.lushui
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
;; Homogeneous lists with a fixed length and related functions.
module

use topmost.type.Type
use topmost.nat.(Nat, +)
use topmost.(
type.Type,
nat.(Nat, +),
)

@public @known
data Vector A: For (n: Nat) -> Type of
Expand Down
2 changes: 1 addition & 1 deletion test/ui/analyze-types.lushui
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use extern.core.(
type.Type,
bool.(false, true, Bool),
)
)

is-nat32-or-nat64 (A: Type -> Type): Bool =
case A of
Expand Down
2 changes: 1 addition & 1 deletion test/ui/any.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use extern.core.(
list.List,
bool.(Bool, false, true),
unit.(Unit, unit),
)
)

data Any: Type of
any: For (A: Type) -> A -> Any
Expand Down
2 changes: 1 addition & 1 deletion test/ui/factorial.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use extern.core.(
bool.(self, Bool, false, true),
nat.(self, Nat),
)
)

main: Nat = factorial 20
;;; main: Nat = factorial 50 ;;; @Note takes several minutes after a rustc update (compared to a second)
Expand Down
2 changes: 1 addition & 1 deletion test/ui/intrinsic.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use extern.core.(
bool.Bool,
list.List,
tuple.Tuple,
)
)

combine: Nat -> Nat -> Nat = nat.+
successor: Nat -> Nat = combine 1
Expand Down
2 changes: 1 addition & 1 deletion test/ui/lengthy-type-mismatch.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use extern.core.(
int.Int,
unit.Unit,
function.identity,
)
)

it: Tuple List.((Type), Int, Unit, Int) =
Tuple.prepend
Expand Down
2 changes: 1 addition & 1 deletion test/ui/lowering/use-path-trees.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ use foo.(A as F1, B as F2)
use topmost.foo.alpha.(
gamma.delta.zeta.(foo, bar),
xoo.moo.doo as XXX
)
)
2 changes: 1 addition & 1 deletion test/ui/name-resolution/exposure/undefined-reach.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use topmost.(
namespaced as indir0,
indir0 as indir1,
indir1 as indir2,
)
)

@(public self.indir2.emptiness)
X: Type = Unit
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use extern.core.(
list.List,
nat32.Nat32,
text.Text,
)
)

construct: List = List.(1, 3, 100, Nat32.0)

Expand Down
2 changes: 1 addition & 1 deletion test/ui/numbers.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use extern.core.(
nat32.Nat32,
int.Int,
int64.Int64,
)
)

alpha: Int = Int.-1000

Expand Down
9 changes: 7 additions & 2 deletions test/ui/packages/transitive-dependencies/main.lushui
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
;;; TEST auxiliary packages/transitive-dependencies

use extern.core.(type.Type, nat.(Nat, ==), bool.Bool)
use extern.core.(tuple.Tuple, list.List)
use extern.core.(
type.Type,
nat.(Nat, ==),
bool.Bool,
tuple.Tuple,
list.List,
)
use extern.alpha.(bet, g-one, jamma)
use extern.gamma.(G as The-G, g1, gam)

Expand Down
2 changes: 1 addition & 1 deletion test/ui/parsing/case-analysis.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ main: Untyped =
use extern.core.(
nat.Nat,
bool.Bool.(self, false, true),
)
)

invert (b: Bool): Bool =
case b of
Expand Down
6 changes: 5 additions & 1 deletion test/ui/punctuation.lushui
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
;;; TEST pass run

use extern.core.nat.(Nat, add as +, multiply as *)
use extern.core.nat.(
Nat,
add as +,
multiply as *,
)

x: Nat = * 1 2

Expand Down
6 changes: 4 additions & 2 deletions test/ui/running-intrinsic-functions.lushui
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
;;; TEST pass run

use extern.core.text.(concat, Text)
use extern.core.nat.(self, Nat)
use extern.core.(
text.(concat, Text),
nat.(self, Nat),
)

base: Nat = 1034032

Expand Down
2 changes: 1 addition & 1 deletion test/ui/use-bindings-are-aliases.lushui
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use extern.core.(
type.Type,
nat.(Nat, Nat as N),
list.List,
)
)

data Source: Type of
source: N -> Source
Expand Down

0 comments on commit d4149d2

Please sign in to comment.