Skip to content

Added setting array index#113

Merged
KrosFire merged 2 commits intomainfrom
array-index-set
Feb 25, 2026
Merged

Added setting array index#113
KrosFire merged 2 commits intomainfrom
array-index-set

Conversation

@KrosFire
Copy link
Member

@KrosFire KrosFire commented Feb 25, 2026

Fixes #112

Summary by CodeRabbit

  • New Features

    • Array element assignment syntax supported with index and value expressions and type validation
    • Generic constraints applied when assigning into generic arrays
  • Bug Fixes / Behavior

    • Stricter numeric type matching (previous Number/Int equivalence removed), affecting type comparisons
  • Tests

    • Added grammar and analysis tests covering array-index assignment, error cases, and generics

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds ArrayIndexSet statement support: parser, semantic tokens, and analysis/type-checking for assignments to array elements (including generic inference and index validation). Updates Statement enum and type-matching logic, and adds grammar and analysis tests covering successful and error scenarios.

Changes

Cohort / File(s) Summary
Grammar — statement variant
crates/grammar/src/alpha050/mod.rs
Added new ArrayIndexSet variant in the public Statement enum.
Grammar — parser
crates/grammar/src/alpha050/statements/array_index_set.rs, crates/grammar/src/alpha050/statements/mod.rs
Added array_index_set_parser to parse var[index] = value and integrated it into the top-level statement choice; new public module exported.
Semantic tokens
crates/grammar/src/alpha050/semantic_tokens.rs
Extended token generation to handle ArrayIndexSet, emitting VARIABLE for the target and tokens for index and value expressions.
Analysis & type checking
crates/analysis/src/alpha050/stmnts.rs
Implemented analysis branch for ArrayIndexSet: validate index is Int, derive array element type (including generics and nested arrays), constrain generics when possible, type-check value against element type, record symbol reference, and propagate combined analysis results.
Type system
crates/types/src/data_type.rs
Removed special-case equivalence between DataType::Number and DataType::Int in matches_type, tightening matching semantics.
Grammar tests
crates/server/tests/grammar/alpha050.rs
Added tests for parsing array index assignment with constant and expression indices.
Analysis tests
crates/server/tests/analysis/alpha050.rs
Added tests covering successful element assignment, assigning into const arrays, indexing non-arrays, type mismatches, and generic inference cases.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Editor
participant Parser
participant Analyzer
participant TypeSystem
participant Symbols
Editor->>Parser: submit source (includes arr[index] = value)
Parser-->>Editor: AST with Statement::ArrayIndexSet
Parser->>Analyzer: analyzed statement node
Analyzer->>Symbols: lookup arr symbol & type
Analyzer->>TypeSystem: request element-type(from arr type, generics)
TypeSystem-->>Analyzer: element type / unresolved generic placeholders
Analyzer->>Analyzer: validate index expr is Int; analyze value expr
Analyzer->>TypeSystem: constrain generics with value type (if applicable)
TypeSystem-->>Analyzer: resolved types or errors
Analyzer->>Symbols: record symbol reference & inferred constraints
Analyzer-->>Editor: analysis result (success or errors)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped along the parser's trail,
I nudged an index, left a tiny tail,
Types whispered secrets, generics learned fast,
Elements settled — assignments held at last,
A joyful thump: arrays embrace their cast.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Added setting array index' directly describes the main change: implementing array element assignment (array[index] = value) support.
Linked Issues check ✅ Passed The PR fully addresses issue #112 by implementing grammar parsing, semantic analysis, and type checking for array element assignment statements.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing array element assignment: parser, analysis, semantic tokens, tests, and one minor type-matching cleanup.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch array-index-set

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
crates/server/tests/analysis/alpha050.rs (1)

442-693: Extract shared backend setup into a helper to eliminate boilerplate duplication.

Each of the five new tests (and all existing tests in this file) repeats ~45 lines of identical setup: LspService::new, backend.files.fs, platform-conditional Path::new, Uri::from_file_path, vfs.write, and open_document. Consider a helper like:

async fn setup_backend(code: &str) -> (Backend, FileId) {
    let (service, _) = tower_lsp_server::LspService::new(|client| {
        Backend::new(client, AmberVersion::Alpha050, Some(Arc::new(MemoryFS::new())))
    });
    let backend = service.inner().clone(); // or keep a ref
    // ... platform path, uri, vfs.write, open_document
    (backend, file_id)
}

This is pre-existing in all tests in the file, so the refactor scope is broader than this PR, but the five new tests are the right moment to introduce it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/server/tests/analysis/alpha050.rs` around lines 442 - 693, Extract the
repeated test setup into an async helper (e.g., async fn setup_backend(code:
&str) -> (Backend, FileId)) that performs LspService::new with Backend::new(…,
AmberVersion::Alpha050, Some(Arc::new(MemoryFS::new()))), gets service.inner()
(clone if needed), builds the platform Path and Uri via Uri::from_file_path,
writes the provided code with vfs.write, and calls open_document to return the
backend and file_id; then replace each test's duplicated block (the
LspService::new/Backend::new creation, vfs.write, Uri::from_file_path, and
open_document calls) with a call to setup_backend(code) and use the returned
Backend and FileId.
crates/grammar/src/alpha050/statements/array_index_set.rs (1)

46-47: Use .labelled() before .boxed() for consistency with the rest of the codebase.

While .boxed() is only for type-erasure and doesn't affect label visibility, the conventional order in this project is .labelled(...).boxed(), as seen in other parser definitions throughout the codebase (e.g., in the expressions modules).

♻️ Proposed fix
-        .boxed()
-        .labelled("array index set")
+        .labelled("array index set")
+        .boxed()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/grammar/src/alpha050/statements/array_index_set.rs` around lines 46 -
47, Change the parser builder so the label is applied before boxing for
consistency: in the array index set parser (the chain that currently ends with
.boxed().labelled("array index set")), swap the calls to use .labelled("array
index set").boxed() instead so the label appears before type-erasure like other
parsers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/analysis/src/alpha050/stmnts.rs`:
- Around line 961-1001: The analyze_exp call for index_exp is ignored so its
is_propagating_failure and return_ty are lost; capture its result (e.g., let
index_analysis = analyze_exp(..., index_exp, ...)), then when constructing the
StmntAnalysisResult combine both analyses: set is_propagating_failure =
index_analysis.is_propagating_failure || exp_analysis.is_propagating_failure and
set return_ty to a sensible merge (e.g.,
index_analysis.return_ty.or(exp_analysis.return_ty) or otherwise prefer the
first non-none), and keep the existing element_ty generic constraint and
insert_symbol_reference logic intact.

In `@crates/server/tests/analysis/alpha050.rs`:
- Around line 683-686: The comment before the assertion about generic inference
is incorrect: examine the call site set_first([1, 2, 3], 42) and update the
comment to reflect the actual inferred types captured in symbol_table.symbols
(e.g., that 'arr' and 'value' are constrained to concrete [Int] and Int if the
snapshot shows that) so the comment matches the snapshot; reference set_first,
'arr', 'value', and symbol_table.symbols when editing the comment to accurately
describe the observed inference outcome.

---

Nitpick comments:
In `@crates/grammar/src/alpha050/statements/array_index_set.rs`:
- Around line 46-47: Change the parser builder so the label is applied before
boxing for consistency: in the array index set parser (the chain that currently
ends with .boxed().labelled("array index set")), swap the calls to use
.labelled("array index set").boxed() instead so the label appears before
type-erasure like other parsers.

In `@crates/server/tests/analysis/alpha050.rs`:
- Around line 442-693: Extract the repeated test setup into an async helper
(e.g., async fn setup_backend(code: &str) -> (Backend, FileId)) that performs
LspService::new with Backend::new(…, AmberVersion::Alpha050,
Some(Arc::new(MemoryFS::new()))), gets service.inner() (clone if needed), builds
the platform Path and Uri via Uri::from_file_path, writes the provided code with
vfs.write, and calls open_document to return the backend and file_id; then
replace each test's duplicated block (the LspService::new/Backend::new creation,
vfs.write, Uri::from_file_path, and open_document calls) with a call to
setup_backend(code) and use the returned Backend and FileId.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e76035e and c6134b1.

⛔ Files ignored due to path filters (17)
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set-2.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set-3.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_const_error-2.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_const_error-3.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_const_error.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_generic-2.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_generic-3.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_generic.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_non_array_error-2.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_non_array_error-3.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_non_array_error.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_type_mismatch_error-2.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_type_mismatch_error-3.snap is excluded by !**/*.snap
  • crates/server/tests/analysis/snapshots/r#mod__analysis__alpha050__array_index_set_type_mismatch_error.snap is excluded by !**/*.snap
  • crates/server/tests/grammar/snapshots/r#mod__grammar__alpha050__array_index_set.snap is excluded by !**/*.snap
  • crates/server/tests/grammar/snapshots/r#mod__grammar__alpha050__array_index_set_expression_index.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • crates/analysis/src/alpha050/stmnts.rs
  • crates/grammar/src/alpha050/mod.rs
  • crates/grammar/src/alpha050/semantic_tokens.rs
  • crates/grammar/src/alpha050/statements/array_index_set.rs
  • crates/grammar/src/alpha050/statements/mod.rs
  • crates/server/tests/analysis/alpha050.rs
  • crates/server/tests/grammar/alpha050.rs
  • crates/types/src/data_type.rs
💤 Files with no reviewable changes (1)
  • crates/types/src/data_type.rs

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 92.92453% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/analysis/src/alpha050/stmnts.rs 69.38% 15 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/analysis/src/alpha050/stmnts.rs (1)

890-906: The variable-lookup + function/constant guard block is duplicated across ~7 match arms.

This exact pattern (lines 891–906) — get_symbol_definition_info → check Function / is_const → fall through to info.data_type / DataType::Any — appears in VariableSet, every Shorthand* arm, and now ArrayIndexSet. Consider extracting a small helper (e.g., resolve_assignable_var_ty) to reduce the duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/analysis/src/alpha050/stmnts.rs` around lines 890 - 906, Extract the
duplicated variable-lookup and guard logic into a helper (e.g.,
resolve_assignable_var_ty) that wraps get_symbol_definition_info and performs
the SymbolType::Function and SymbolType::Variable(var) if var.is_const checks,
returning the resolved DataType (or DataType::Any) and reporting errors via
files.report_error as currently done; then replace the duplicated blocks in
Statement::ArrayIndexSet, VariableSet, all Shorthand* arms, etc., by calling
resolve_assignable_var_ty(file/files, var, var_span) to get var_ty. Ensure the
helper preserves the existing error messages and uses the same
parameters/behavior so callers only need to accept the returned DataType.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/analysis/src/alpha050/stmnts.rs`:
- Around line 890-906: Extract the duplicated variable-lookup and guard logic
into a helper (e.g., resolve_assignable_var_ty) that wraps
get_symbol_definition_info and performs the SymbolType::Function and
SymbolType::Variable(var) if var.is_const checks, returning the resolved
DataType (or DataType::Any) and reporting errors via files.report_error as
currently done; then replace the duplicated blocks in Statement::ArrayIndexSet,
VariableSet, all Shorthand* arms, etc., by calling
resolve_assignable_var_ty(file/files, var, var_span) to get var_ty. Ensure the
helper preserves the existing error messages and uses the same
parameters/behavior so callers only need to accept the returned DataType.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6134b1 and 216d5fa.

📒 Files selected for processing (2)
  • crates/analysis/src/alpha050/stmnts.rs
  • crates/server/tests/analysis/alpha050.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/server/tests/analysis/alpha050.rs

@KrosFire KrosFire merged commit 40cc300 into main Feb 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error on array subscript assignment

1 participant