diff --git a/Cargo.lock b/Cargo.lock index 30d26b53b..176590a3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,7 +68,7 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "bend-lang" -version = "0.2.18" +version = "0.2.19" dependencies = [ "TSPL", "arrayvec", diff --git a/Cargo.toml b/Cargo.toml index d4f22e621..5c2c498e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "bend-lang" description = "A high-level, massively parallel programming language" license = "Apache-2.0" -version = "0.2.18" +version = "0.2.19" edition = "2021" exclude = ["tests/snapshots/"] diff --git a/docs/syntax.md b/docs/syntax.md index 69430329d..9cb9d5b93 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -46,7 +46,7 @@ def main: A function definition is composed by a name, a sequence of parameters and a body. -A top-level name can be anything matching the regex `[A-Za-z0-9_.-/]+`, except it can't have `__` (used for generated names). +A top-level name can be anything matching the regex `[A-Za-z0-9_.-/]+`, except it can't have `__` (used for generated names) or start with `//`. The last statement of each function must either be a `return` or a selection statement (`if`, `switch`, `match`, `fold`) where all branches `return`. @@ -372,7 +372,10 @@ some_var foo/bar ``` -A variable can be anything matching the regex `[A-Za-z0-9_.-/]+`. +A variable can be anything matching the regex `[A-Za-z0-9_.-/]+` but with some restrictions: + +- It can not start with `//` +- It can not contain `__` A variable is a name for some immutable expression. It is possible to rebind variables with the same name. @@ -618,7 +621,7 @@ Name (Ctr1 sub_arg1 sub_arg2) arg3 = rule0_body Name Ctr2 arg3 = rule1_body ``` -A top-level name can be anything matching the regex `[A-Za-z0-9_.-/]+`, except it can't have `__` (used for generated names). +A top-level name can be anything matching the regex `[A-Za-z0-9_.-/]+`, except it can't have `__` (used for generated names) or start with `//`. ### Function Definitions @@ -681,7 +684,10 @@ The constructors inherit the name of their types and become functions (`Tree/Nod ### Variables -A variable can be anything matching the regex `[A-Za-z0-9_.-/]+`. +A variable can be anything matching the regex `[A-Za-z0-9_.-/]+` but with some restrictions: + +- It can not start with `//` +- It can not contain `__` A variable is a name for some immutable expression. It is possible to rebind variables with the same name. diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 807220515..8dc0958ad 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -805,24 +805,31 @@ pub trait ParserCommons<'a>: Parser<'a> { } } - fn parse_top_level_name(&mut self) -> ParseResult { + fn parse_restricted_name(&mut self, kind: &str) -> ParseResult { let ini_idx = *self.index(); - let nam = self.parse_bend_name()?; + let name = self.take_while(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.' || c == '-' || c == '/'); + if name.is_empty() { + self.expected("name")? + } + let name = Name::new(name.to_owned()); let end_idx = *self.index(); - if nam.contains("__") { - let msg = "Top-level names are not allowed to contain \"__\".".to_string(); + if name.contains("__") { + let msg = format!("{kind} names are not allowed to contain \"__\"."); self.with_ctx(Err(msg), ini_idx, end_idx) - } else if nam.starts_with("//") { - let msg = "Top-level names are not allowed to start with \"//\".".to_string(); + } else if name.starts_with("//") { + let msg = format!("{kind} names are not allowed to start with \"//\"."); self.with_ctx(Err(msg), ini_idx, end_idx) } else { - Ok(nam) + Ok(name) } } + fn parse_top_level_name(&mut self) -> ParseResult { + self.parse_restricted_name("Top-level") + } + fn parse_bend_name(&mut self) -> ParseResult { - let name = self.take_while(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.' || c == '-' || c == '/'); - if name.is_empty() { self.expected("name") } else { Ok(Name::new(name.to_owned())) } + self.parse_restricted_name("Variable") } /// Consumes exactly the text without skipping. diff --git a/tests/golden_tests/compile_file/variable_name_double_underscore.bend b/tests/golden_tests/compile_file/variable_name_double_underscore.bend new file mode 100644 index 000000000..db204ccbc --- /dev/null +++ b/tests/golden_tests/compile_file/variable_name_double_underscore.bend @@ -0,0 +1,2 @@ +def main: + return __this_should_fail__(*) diff --git a/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap b/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap new file mode 100644 index 000000000..667887ed5 --- /dev/null +++ b/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap @@ -0,0 +1,9 @@ +--- +source: tests/golden_tests.rs +input_file: tests/golden_tests/compile_file/variable_name_double_underscore.bend +--- +Errors: +In tests/golden_tests/compile_file/variable_name_double_underscore.bend : +- expected: expression +- detected: + 2 | return __this_should_fail__(*)