Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion docs/language/lists.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ list point points; # empty list of points.
list point points = [100, 200, 300, 400]; # points[1] == point {x: 100, y: 200} and so on...
```

### With a fixed length

Use `[value; length]` to make a list whose items all start with the same value.

```goboscript
list scores = [0; 1000]; # 1,000 items, all set to 0.
list names = [""; 25]; # 25 empty strings.
```

This form also works with struct lists. The starting value is used for each field.

```goboscript
struct point {x, y}
list point points = [0; 100]; # 100 points whose x and y fields are both 0.
```

The length cannot be negative, infinite, `NaN`, or greater than 200,000.

### Read contents from a text file

This allows you to load a text file line-by-line into a list of strings.
Expand Down Expand Up @@ -123,4 +141,3 @@ value = list_name["last"];
| `list_name[index] //= y;` | ![](../assets/list_floor_divide.png){width="400"} |
| `list_name[index] %= y;` | ![](../assets/list_mod.png){width="400"} |
| `list_name[index] &= y;` | ![](../assets/list_join.png){width="400"} |

17 changes: 17 additions & 0 deletions src/ast/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct List {
pub enum ListDefault {
Values(Vec<ConstExpr>),
File { path: SmolStr, span: Span },
FixedLength(ConstExpr, ConstExpr),
}

impl List {
Expand Down Expand Up @@ -63,4 +64,20 @@ impl List {
is_used: false,
}
}

pub fn new_fixed_length(
name: SmolStr,
span: Span,
type_: Type,
default: ConstExpr,
length: ConstExpr,
) -> Self {
Self {
name,
span,
type_,
default: Some(ListDefault::FixedLength(default, length)),
is_used: false,
}
}
}
16 changes: 16 additions & 0 deletions src/codegen/sb3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,22 @@ where T: Write + Seek
vec![]
}
},
Some(ListDefault::FixedLength(value, length)) => {
let multiplier = list
.type_
.struct_()
.and_then(|(struct_name, _)| s.get_struct(struct_name))
.map(|struct_| struct_.fields.len())
.unwrap_or(1);
let value = s.evaluate_const_expr(d, value);
let len = s.evaluate_const_expr(d, length).to_number();
Comment thread
aspizu marked this conversation as resolved.
if len > 200_00_f64 || len.is_nan() || len.is_infinite() || len < 0_f64 {
d.report(DiagnosticKind::FixedLengthListInvalid(len), &length.span());
vec![]
} else {
vec![value; len as usize * multiplier]
}
}
None => vec![],
};
match &list.type_ {
Expand Down
18 changes: 18 additions & 0 deletions src/diagnostic/diagnostic_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
ast::{
Sprite,
Type,
Value,
},
blocks::{
Block,
Expand Down Expand Up @@ -127,6 +128,7 @@ pub enum DiagnosticKind {
UnusedFunc(SmolStr),
UnusedArg(SmolStr),
UnusedStructField(SmolStr),
FixedLengthListInvalid(f64),
}

impl DiagnosticKind {
Expand Down Expand Up @@ -298,6 +300,21 @@ impl DiagnosticKind {
format!("duplicate variant {variant_name} in enum {enum_name}")
}
DiagnosticKind::EmptyStruct(name) => format!("struct {name} is empty"),
DiagnosticKind::FixedLengthListInvalid(value) => {
if *value < 0_f64 {
return format!("list length cannot be negative");
}
if value.is_infinite() {
return format!("list length cannot be infinite");
}
if value.is_nan() {
return format!("list length cannot be nan");
}
if *value > 200_000_f64 {
return format!("list length cannot be greater than 200,000");
}
unreachable!()
}
}
}

Expand Down Expand Up @@ -485,6 +502,7 @@ impl From<&DiagnosticKind> for Level {
| DiagnosticKind::InvalidCostumeFormat { .. }
| DiagnosticKind::InvalidSoundFormat { .. }
| DiagnosticKind::LocalNotSupported
| DiagnosticKind::FixedLengthListInvalid(..)
| DiagnosticKind::UnknownDirective(_) => Level::Error,

| DiagnosticKind::FollowedByUnreachableCode
Expand Down
3 changes: 3 additions & 0 deletions src/parser/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ Declr: () = {
LIST <type_:Type> <l:@L> <name:NAME> <r:@R> <pl:@L> <path:STR> <pr:@R> ";" => {
sprite.add_list(List::new_file(name, l..r, type_, path, pl..pr), diagnostics);
},
LIST <type_:Type> <l:@L> <name:NAME> <r:@R> "=" "[" <default:ConstExpr> ";" <length:ConstExpr> "]" ";" => {
sprite.add_list(List::new_fixed_length(name, l..r, type_, default, length), diagnostics);
}
}

EnumVariant: EnumVariant = {
Expand Down
Loading