Skip to content

Commit

Permalink
Merge pull request #487 from HigherOrderCO/478-dont-allow-variable-na…
Browse files Browse the repository at this point in the history
…mes-to-contain-__

478 dont allow variable names to contain "__"
  • Loading branch information
developedby authored May 24, 2024
2 parents cdbaf66 + f929320 commit cfd9b03
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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/"]

Expand Down
14 changes: 10 additions & 4 deletions docs/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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.

Expand Down
25 changes: 16 additions & 9 deletions src/fun/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,24 +805,31 @@ pub trait ParserCommons<'a>: Parser<'a> {
}
}

fn parse_top_level_name(&mut self) -> ParseResult<Name> {
fn parse_restricted_name(&mut self, kind: &str) -> ParseResult<Name> {
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<Name> {
self.parse_restricted_name("Top-level")
}

fn parse_bend_name(&mut self) -> ParseResult<Name> {
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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def main:
return __this_should_fail__(*)
Original file line number Diff line number Diff line change
@@ -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__(*)

0 comments on commit cfd9b03

Please sign in to comment.