Skip to content

Commit

Permalink
Space-precedence does not apply to value-level operators (#10597)
Browse files Browse the repository at this point in the history
In a sequence of value-level operators, whitespace does not affect relative precedence. Functional operators still follow the space-precedence rules.

The "functional" operators are: `>> << |> |>> <| <<| : .`, application, and any operator containing `<-` or `->`. All other operators are considered value-level operators.

Asymmetric whitespace can still be used to form *operator sections* of value-level operators, e.g. `+2 * 3` is still equivalent to `x -> (x+2) * 3`.

Precedence of application is unchanged, so `f x+y` is still equivalent to `f (x + y)` and `f x+y * z` is still equivalent to `(f (x + y)) * z`.

Any attempt to use spacing to override value-level operator precedence will be caught by the new enso linter. Mixed spacing (for clarity) in value-operator expressions is allowed, as long as it is consistent with the precedences of the operators.

Closes #10366.

# Important Notes
Precedence warnings:
- The parser emits a warning if the whitespace in an expression is inconsistent with its effective precedence.
- A new enso linter can be run with `./run libraries lint`. It parses all `.enso` files in `distribution/lib` and `test`, and reports any errors or warnings. It can also be run on individual files: `cargo run --release --bin check_syntax -- file1 file2...` (the result may be easier to read than the `./run` output).
- The linter is also run as part of `./run lint`, so it is checked in CI.

Additional language change:
- The exponentiation operator (`^`) now has higher precedence than the multiplication class (`*`, `/`, `%`). This change did not affect any current enso files.

Library changes:
- The libraries have been updated. The new warnings were used to identify all affected code; the changes themselves have not been programmatically verified (in many cases their equivalence relies on the commutativity of string concatenation).

(cherry picked from commit e5b85bf)
  • Loading branch information
kazcw authored and jdunkerley committed Jul 24, 2024
1 parent 78c31e8 commit 7f52a82
Show file tree
Hide file tree
Showing 43 changed files with 958 additions and 382 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

- [Enforce conversion method return type][10468]
- [Renaming launcher executable to ensoup][10535]
- [Space-precedence does not apply to value-level operators][10597]

[10468]: https://github.com/enso-org/enso/pull/10468
[10535]: https://github.com/enso-org/enso/pull/10535
[10597]: https://github.com/enso-org/enso/pull/10597

#### Enso IDE

Expand Down
38 changes: 38 additions & 0 deletions app/gui2/src/util/ast/__tests__/__snapshots__/raw.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ exports[`Parsing '2
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 4,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 4,
},
Expand Down Expand Up @@ -124,6 +125,7 @@ exports[`Parsing '2
"spanLeftOffsetCodeStartLine": 2,
"spanLeftOffsetCodeStartUtf8": 9,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 9,
},
Expand Down Expand Up @@ -197,6 +199,7 @@ exports[`Parsing '2
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -208,6 +211,7 @@ exports[`Parsing '2
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "OperatorBlockApplication",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -231,6 +235,7 @@ exports[`Parsing '2
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down Expand Up @@ -282,6 +287,7 @@ exports[`Parsing 'Data.read
"whitespaceStartInCodeBuffer": 0,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -336,6 +342,7 @@ exports[`Parsing 'Data.read
"whitespaceStartInCodeBuffer": 5,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 5,
},
Expand All @@ -347,6 +354,7 @@ exports[`Parsing 'Data.read
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -401,6 +409,7 @@ exports[`Parsing 'Data.read
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 10,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 10,
},
Expand Down Expand Up @@ -454,6 +463,7 @@ exports[`Parsing 'Data.read
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 13,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 13,
},
Expand All @@ -465,6 +475,7 @@ exports[`Parsing 'Data.read
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 10,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 10,
},
Expand All @@ -488,6 +499,7 @@ exports[`Parsing 'Data.read
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down Expand Up @@ -574,6 +586,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 9,
"type": "TextLiteral",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 9,
},
Expand Down Expand Up @@ -611,6 +624,7 @@ exports[`Parsing 'Data.read "File"
"whitespaceStartInCodeBuffer": 0,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -665,6 +679,7 @@ exports[`Parsing 'Data.read "File"
"whitespaceStartInCodeBuffer": 5,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 5,
},
Expand All @@ -676,6 +691,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -687,6 +703,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "App",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -741,6 +758,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 17,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 17,
},
Expand Down Expand Up @@ -794,6 +812,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 20,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 20,
},
Expand All @@ -805,6 +824,7 @@ exports[`Parsing 'Data.read "File"
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 17,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 17,
},
Expand All @@ -828,6 +848,7 @@ exports[`Parsing 'Data.read "File"
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down Expand Up @@ -878,6 +899,7 @@ exports[`Parsing 'Data.read File
"whitespaceStartInCodeBuffer": 10,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 9,
},
Expand Down Expand Up @@ -915,6 +937,7 @@ exports[`Parsing 'Data.read File
"whitespaceStartInCodeBuffer": 0,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -969,6 +992,7 @@ exports[`Parsing 'Data.read File
"whitespaceStartInCodeBuffer": 5,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 5,
},
Expand All @@ -980,6 +1004,7 @@ exports[`Parsing 'Data.read File
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -991,6 +1016,7 @@ exports[`Parsing 'Data.read File
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "App",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -1045,6 +1071,7 @@ exports[`Parsing 'Data.read File
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 15,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 15,
},
Expand Down Expand Up @@ -1098,6 +1125,7 @@ exports[`Parsing 'Data.read File
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 18,
"type": "Number",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 18,
},
Expand All @@ -1109,6 +1137,7 @@ exports[`Parsing 'Data.read File
"spanLeftOffsetCodeStartLine": 1,
"spanLeftOffsetCodeStartUtf8": 15,
"type": "OprApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 15,
},
Expand All @@ -1132,6 +1161,7 @@ exports[`Parsing 'Data.read File
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down Expand Up @@ -1182,6 +1212,7 @@ exports[`Parsing 'foo bar
"whitespaceStartInCodeBuffer": 4,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 1,
"whitespaceStartInCodeParsed": 3,
},
Expand Down Expand Up @@ -1217,6 +1248,7 @@ exports[`Parsing 'foo bar
"whitespaceStartInCodeBuffer": 0,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -1228,6 +1260,7 @@ exports[`Parsing 'foo bar
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "App",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -1271,6 +1304,7 @@ exports[`Parsing 'foo bar
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down Expand Up @@ -1320,6 +1354,7 @@ exports[`Parsing 'foo bar=baz' 1`] = `
"whitespaceStartInCodeBuffer": 8,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 8,
},
Expand Down Expand Up @@ -1373,6 +1408,7 @@ exports[`Parsing 'foo bar=baz' 1`] = `
"whitespaceStartInCodeBuffer": 0,
},
"type": "Ident",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand Down Expand Up @@ -1406,6 +1442,7 @@ exports[`Parsing 'foo bar=baz' 1`] = `
"spanLeftOffsetCodeStartLine": 0,
"spanLeftOffsetCodeStartUtf8": 0,
"type": "NamedApp",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
},
Expand All @@ -1429,6 +1466,7 @@ exports[`Parsing 'foo bar=baz' 1`] = `
},
],
"type": "BodyBlock",
"warnings": [],
"whitespaceLengthInCodeParsed": 0,
"whitespaceStartInCodeParsed": 0,
}
Expand Down
1 change: 1 addition & 0 deletions build/build/paths.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<edition>.yaml:
enso.bundle.template:
launcher-manifest.yaml:
lib:
engine/:
runner/:
src/:
Expand Down
1 change: 1 addition & 0 deletions build/build/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ use crate::prelude::*;
// === Export ===
// ==============

pub mod enso_linter;
pub mod parser;
36 changes: 36 additions & 0 deletions build/build/src/rust/enso_linter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use super::*;

use ide_ci::programs::cargo;
use ide_ci::programs::Cargo;

use crate::paths::generated::RepoRoot;

const LINTER_CRATE_NAME: &str = "enso-parser-debug";
const LINTER_BIN_NAME: &str = "check_syntax";
const ENSO_EXTENSION: &str = ".enso";

pub fn cargo_run_linter_cmd(repo_root: &Path) -> Result<Command> {
let mut ret = Cargo.cmd()?;
ret.current_dir(repo_root)
.apply(&cargo::Command::Run)
.apply(&cargo::Options::Package(LINTER_CRATE_NAME.into()))
.apply(&cargo::RunOption::Bin(LINTER_BIN_NAME.into()))
.apply(&cargo::RunOption::Release);
Ok(ret)
}

fn collect_source_paths(repo_root: &RepoRoot) -> Result<Vec<PathBuf>> {
let glob_pattern = format!("**/*{ENSO_EXTENSION}");
let source_roots = [&repo_root.distribution.lib.path, &repo_root.test.path];
let glob_paths: Vec<_> = source_roots
.into_iter()
.map(|path| glob::glob(path.join(&glob_pattern).as_str()))
.collect::<std::result::Result<_, _>>()?;
Ok(glob_paths.into_iter().flatten().collect::<std::result::Result<_, _>>()?)
}

pub async fn lint_all(repo_root: RepoRoot) -> Result<()> {
let sources = collect_source_paths(&repo_root)?;
cargo_run_linter_cmd(&repo_root)?.arg("--").args(sources).run_ok().await?;
Ok(())
}
3 changes: 3 additions & 0 deletions build/ci_utils/src/programs/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ impl Manipulator for Options {
pub enum RunOption {
/// Name of the bin target to run.
Bin(String),
/// Build in release mode.
Release,
}

impl Manipulator for RunOption {
Expand All @@ -135,6 +137,7 @@ impl Manipulator for RunOption {
Bin(binary_name) => {
command.arg(binary_name.as_str());
}
Release => {}
}
}
}
Expand Down
Loading

0 comments on commit 7f52a82

Please sign in to comment.