Skip to content

Commit

Permalink
allow for a name in scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Jun 25, 2024
1 parent 4368078 commit ae7d15f
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 52 deletions.
2 changes: 1 addition & 1 deletion site/src/editor/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ pub fn progressive_strings(input: &str) -> Vec<String> {
Item::Binding(binding) => {
lines.push(vec![binding.span().as_str(&inputs, |s| s.into())])
}
Item::TestScope(items) => lines.push(vec![items.span.as_str(&inputs, |s| s.into())]),
Item::Module(items) => lines.push(vec![items.span.as_str(&inputs, |s| s.into())]),
Item::Import(import) => lines.push(vec![import.span().as_str(&inputs, |s| s.into())]),
}
}
Expand Down
13 changes: 11 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub enum Item {
Binding(Binding),
/// An import
Import(Import),
/// A test scope
TestScope(Sp<Vec<Item>>),
/// A scope
Module(Sp<ScopedModule>),
}

/// A binding
Expand Down Expand Up @@ -51,6 +51,15 @@ impl Binding {
}
}

/// A scoped module
#[derive(Debug, Clone)]
pub struct ScopedModule {
/// The name of the scope
pub name: Option<Sp<Ident>>,
/// The items
pub items: Vec<Item>,
}

/// An import
#[derive(Debug, Clone)]
pub struct Import {
Expand Down
25 changes: 16 additions & 9 deletions src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ pub(crate) struct Scope {

#[derive(Clone, Copy, PartialEq, Eq)]
enum ScopeKind {
/// A scope at the top level of a file
File,
/// A scope at the top level of a file or in a named module
Module,
/// A temporary scope, probably for a macro
Temp,
/// A test scope between `---`s
Expand All @@ -184,7 +184,7 @@ enum ScopeKind {
impl Default for Scope {
fn default() -> Self {
Self {
kind: ScopeKind::File,
kind: ScopeKind::Module,
file_path: None,
comment: None,
names: IndexMap::new(),
Expand Down Expand Up @@ -493,9 +493,16 @@ code:
(words.iter()).any(|w| matches!(&w.value, Word::SemanticComment(_)))
}
let mut lines = match item {
Item::TestScope(items) => {
Item::Module(module) => {
prev_comment.take();
self.in_scope(ScopeKind::Test, |env| env.items(items.value, true))?;
let is_test =
(module.value.name.as_ref()).map_or(true, |name| name.value == "test");
let scope_kind = if is_test {
ScopeKind::Test
} else {
ScopeKind::Module
};
self.in_scope(scope_kind, |env| env.items(module.value.items, true))?;
return Ok(());
}
Item::Words(lines) => lines,
Expand Down Expand Up @@ -770,7 +777,7 @@ code:
format!("Cycle detected importing {}", path.to_string_lossy()),
));
}
let import = self.in_scope(ScopeKind::File, |env| {
let import = self.in_scope(ScopeKind::Module, |env| {
env.load_str_src(&input, &path).map(drop)
})?;
self.imports.insert(path.clone(), import);
Expand Down Expand Up @@ -1504,8 +1511,8 @@ code:
}
let mut hit_file = false;
for scope in self.higher_scopes.iter().rev() {
if scope.kind == ScopeKind::File {
if hit_file || self.scope.kind == ScopeKind::File {
if scope.kind == ScopeKind::Module {
if hit_file || self.scope.kind == ScopeKind::Module {
break;
}
hit_file = true;
Expand Down Expand Up @@ -2169,7 +2176,7 @@ code:
.or_else(|| {
self.higher_scopes
.last()
.filter(|_| self.scope.kind != ScopeKind::File)
.filter(|_| self.scope.kind != ScopeKind::Module)
.and_then(|scope| scope.names.get(name))
})
.map_or(true, |l| l.index != local.index)
Expand Down
2 changes: 1 addition & 1 deletion src/compile/modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1290,7 +1290,7 @@ impl Compiler {
Item::Import(import) => self
.import(import, None)
.map_err(|e| e.trace_macro(span.clone()))?,
Item::TestScope(_) => {
Item::Module(_) => {
self.add_error(span.clone(), "Macros may not generate test scopes")
}
};
Expand Down
59 changes: 43 additions & 16 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ type GlyphMap = Vec<(CodeSpan, (Loc, Loc))>;

impl<'a> Formatter<'a> {
fn format_top_items(mut self, items: &[Item]) -> (String, GlyphMap) {
self.format_items(items);
self.format_items(items, 0);
let mut output = self.output;
while output.ends_with('\n') {
output.pop();
Expand All @@ -497,10 +497,12 @@ impl<'a> Formatter<'a> {
}
(output, self.glyph_map)
}
fn format_items(&mut self, items: &[Item]) {
for item in items {
self.format_item(item);
self.output.push('\n');
fn format_items(&mut self, items: &[Item], depth: usize) {
for (i, item) in items.iter().enumerate() {
if i > 0 || depth > 0 {
self.newline(depth);
}
self.format_item(item, depth);
}
// Align end-of-line comments
if self.config.align_comments && !self.end_of_line_comments.is_empty() {
Expand Down Expand Up @@ -573,19 +575,37 @@ impl<'a> Formatter<'a> {
self.output = new_output;
}
}
fn format_item(&mut self, item: &Item) {
fn newline(&mut self, depth: usize) {
self.output.push('\n');
self.indent(depth);
}
fn indent(&mut self, depth: usize) {
for _ in 0..self.config.multiline_indent * depth {
self.output.push(' ');
}
}
fn format_item(&mut self, item: &Item, depth: usize) {
if depth == 0 {
dbg!(item);
}
match item {
Item::TestScope(items) => {
Item::Module(m) => {
self.prev_import_function = None;
self.output.push_str("---");
self.output.push('\n');
self.format_items(&items.value);
if let Some(name) = &m.value.name {
self.push(&name.span, &name.value);
}
self.format_items(&m.value.items, depth + 1);
if self.output.ends_with('\n') {
self.output.pop();
}
self.newline(depth);
self.output.push_str("---");
}
Item::Words(lines) => {
self.prev_import_function = None;
let lines = unsplit_words(lines.iter().cloned().flat_map(split_words).collect());
self.format_multiline_words(&lines, false, false, 0);
self.format_multiline_words(&lines, false, false, false, depth);
}
Item::Binding(binding) => {
match binding.words.first().map(|w| &w.value) {
Expand Down Expand Up @@ -624,7 +644,7 @@ impl<'a> Formatter<'a> {
.unwrap_or_else(|| binding.arrow_span.clone());
let mut lines = unsplit_words(split_words(binding.words.clone()));
if lines.len() == 1 {
self.format_words(&lines[0], true, 0);
self.format_words(&lines[0], true, depth);
} else {
lines.push(Vec::new());
self.format_words(
Expand All @@ -635,7 +655,7 @@ impl<'a> Formatter<'a> {
closed: true,
}))],
true,
0,
depth,
);
}
}
Expand Down Expand Up @@ -873,7 +893,13 @@ impl<'a> Formatter<'a> {
self.output.pop();
}
}
self.format_multiline_words(&arr.lines, arr.signature.is_none(), true, depth + 1);
self.format_multiline_words(
&arr.lines,
arr.signature.is_none(),
true,
true,
depth + 1,
);
if arr.boxes {
self.output.push('}');
} else {
Expand Down Expand Up @@ -915,7 +941,7 @@ impl<'a> Formatter<'a> {
self.output.pop();
}
}
self.format_multiline_words(&func.lines, false, true, depth + 1);
self.format_multiline_words(&func.lines, false, true, true, depth + 1);
self.output.push(')');
}
Word::Pack(pack) => {
Expand Down Expand Up @@ -954,7 +980,7 @@ impl<'a> Formatter<'a> {
self.output.pop();
}
}
self.format_multiline_words(&br.value.lines, false, false, depth + 1);
self.format_multiline_words(&br.value.lines, false, false, true, depth + 1);
if any_multiline
&& br.value.lines.last().is_some_and(|line| !line.is_empty())
&& !self.output.trim_end_matches(' ').ends_with('\n')
Expand Down Expand Up @@ -1115,6 +1141,7 @@ impl<'a> Formatter<'a> {
lines: &[Vec<Sp<Word>>],
allow_compact: bool,
allow_leading_space: bool,
allow_trailing_newline: bool,
depth: usize,
) {
if lines.is_empty() {
Expand Down Expand Up @@ -1174,7 +1201,7 @@ impl<'a> Formatter<'a> {
self.format_words(line, true, depth);
}

if !compact {
if allow_trailing_newline && !compact {
if depth > 0 && !lines.iter().last().is_some_and(|line| line.is_empty()) {
self.output.push('\n');
}
Expand Down
15 changes: 2 additions & 13 deletions src/lex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,11 +775,6 @@ impl<'a> Lexer<'a> {
}
fn run(mut self) -> (Vec<Sp<Token>>, Vec<Sp<LexError>>) {
use {self::AsciiToken::*, Token::*};
// Initial scope delimiters
let start = self.loc;
if self.next_chars_exact(["-", "-", "-"]) {
self.end(TripleMinus, start);
}
// Main loop
'main: loop {
let start = self.loc;
Expand All @@ -801,6 +796,7 @@ impl<'a> Lexer<'a> {
"_" => self.end(Underscore, start),
"|" => self.end(Bar, start),
";" => self.end(Semicolon, start),
"-" if self.next_chars_exact(["-", "-"]) => self.end(TripleMinus, start),
"'" if self.next_char_exact("'") => {
if let Some(swiz) = self.array_swizzle() {
self.end(ArraySwizzle(swiz), start)
Expand Down Expand Up @@ -1070,14 +1066,7 @@ impl<'a> Lexer<'a> {
self.end(Number, start)
}
// Newlines
"\n" | "\r\n" => {
self.end(Newline, start);
// Scope delimiters
let start = self.loc;
if self.next_chars_exact(["-", "-", "-"]) {
self.end(TripleMinus, start);
}
}
"\n" | "\r\n" => self.end(Newline, start),
" " | "\t" => {
while self.next_char_exact(" ") || self.next_char_exact("\t") {}
self.end(Spaces, start)
Expand Down
2 changes: 1 addition & 1 deletion src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl Spanner {
let mut spans = Vec::new();
for item in items {
match item {
Item::TestScope(items) => spans.extend(self.items_spans(&items.value)),
Item::Module(m) => spans.extend(self.items_spans(&m.value.items)),
Item::Words(lines) => {
for line in lines {
spans.extend(self.words_spans(line))
Expand Down
24 changes: 15 additions & 9 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ pub fn parse(
next_output_comment: 0,
depth: 0,
};
let items = parser.items(true);
let items = parser.items(false);
if parser.errors.is_empty() && parser.index < parser.tokens.len() {
parser.errors.push(
parser
Expand Down Expand Up @@ -282,13 +282,13 @@ impl<'i> Parser<'i> {
));
self.errors.push(err);
}
fn items(&mut self, parse_scopes: bool) -> Vec<Item> {
fn items(&mut self, in_scope: bool) -> Vec<Item> {
let mut items = Vec::new();
while self.try_exact(Newline).is_some() {
self.try_spaces();
}
loop {
match self.try_item(parse_scopes) {
match self.try_item(in_scope) {
Some(item) => items.push(item),
None => {
if self.try_exact(Newline).is_none() {
Expand All @@ -308,7 +308,7 @@ impl<'i> Parser<'i> {
}
items
}
fn try_item(&mut self, parse_scopes: bool) -> Option<Item> {
fn try_item(&mut self, in_scope: bool) -> Option<Item> {
self.try_spaces();
Some(if let Some(binding) = self.try_binding() {
Item::Binding(binding)
Expand All @@ -319,18 +319,24 @@ impl<'i> Parser<'i> {
// Convert multiline words into multiple items
if !lines.is_empty() {
Item::Words(lines)
} else if parse_scopes {
} else {
let backup = self.index;
let start = self.try_exact(TripleMinus.into())?;
let items = self.items(false);
self.try_spaces();
let name = self.try_ident();
if in_scope && name.is_none() {
self.index = backup;
return None;
}
let items = self.items(true);
let span = if let Some(end) = self.try_exact(TripleMinus.into()) {
start.merge(end)
} else {
self.errors.push(self.expected([TripleMinus]));
start
};
Item::TestScope(span.sp(items))
} else {
return None;
let module = ScopedModule { name, items };
Item::Module(span.sp(module))
}
})
}
Expand Down

0 comments on commit ae7d15f

Please sign in to comment.