Skip to content

Feature: Implement Destructuring Assignments (Object and Array) #7

Description

@dev-kas

Feature: Implement Destructuring Assignments (Object and Array)

Problem/Motivation

Currently, VirtLang's variable declarations (let, const) and assignments (=) are limited to single identifiers or direct member expressions (e.g., let x = 10;, myObject.prop = value;, myArray[index] = value;). While functional, this often leads to verbose code when extracting multiple values from objects or arrays. For example, to get two properties from an object, we write:

let data = { name: "User", age: 30, email: "user@example.com" }
let userName = data.name
let userAge = data.age
print(userName, userAge) // User 30

Similarly, for arrays:

let coordinates = [10, 20, 5]
let x = coordinates[0]
let y = coordinates[1]
print(x, y) // 10 20

This verbosity can reduce readability and boilerplate in common scenarios, especially when dealing with function returns that are structured objects or arrays.

Proposed Solution

I propose adding support for destructuring assignments for both objects and arrays. This feature would allow developers to unpack values from arrays or properties from objects into distinct variables using a more concise syntax.

Examples of desired syntax and behavior:

1. Object Destructuring:

// Basic object destructuring
let person = { name: "Jedi", age: 30 }
let { name, age } = person
print(name, age) // Jedi 30

// Destructuring with renaming
let item = { product: "Laptop", price: 1200 }
let { product: itemName, price: itemPrice } = item
print(itemName, itemPrice) // Laptop 1200

// Destructuring with default values (future consideration, but good to note)
let settings = { theme: "dark" }
let { theme, fontSize = 16 } = settings
print(theme, fontSize) // dark 16

// Nested object destructuring
let config = { server: { host: "localhost", port: 8080 } }
let { server: { host, port } } = config
print(host, port) // localhost 8080

2. Array Destructuring:

// Basic array destructuring
let rgb = ["red", "green", "blue"]
let [r, g, b] = rgb
print(r, g, b) // red green blue

// Skipping elements
let scores = [100, 95, 80]
let [firstScore, , thirdScore] = scores // Skip the middle element
print(firstScore, thirdScore) // 100 80

// Rest element (capturing remaining items)
let numbers = [1, 2, 3, 4, 5]
let [first, second, ...rest] = numbers
print(first, second, rest) // 1 2 [3, 4, 5]

// Using destructuring in function parameters (anonymous functions for now)
let processPerson = fn({ name, age }) {
    print("Processing:", name, "who is", age, "years old.")
}
processPerson({ name: "James", age: 25 }) // Processing: James who is 25 years old.

(Note: Direct function declaration parameter destructuring fn processPerson({ name, age }) might require separate AST changes for FnDeclaration besides VarDeclaration/VarAssignmentExpr)

Technical Implications

Implementing this feature will primarily require changes in the parser and evaluator components.

1. Parser (virtlang-go/parser/)

  • New AST Nodes: We'd need new Expr types to represent destructuring patterns on the LHS of declarations/assignments. For example, ObjectPattern and ArrayPattern. These would contain Property (for objects, similar to ObjectLiteral's properties but representing a pattern) or nested Expr (for arrays).
  • parseVarDecl & parseAssignmentExpr Modifications:
    • These functions would need to check if the Identifier token is followed by a { or [ at the start of the assignment target.
    • If so, they would delegate to new parsing functions (e.g., parseObjectPattern, parseArrayPattern) instead of parseIdentifier or parseMemberExpr for the Assignee or Identifier field.
  • Pattern Parsing Logic:
    • Object Patterns: Handle key-value pairs (prop: newName), shorthand (prop), and potential rest properties (...rest).
    • Array Patterns: Handle elements (elem), skipped elements (empty space between commas), and rest elements (...rest).
  • Error Handling: Proper syntax errors should be emitted for invalid destructuring patterns (e.g., let { 123 } = obj;, let [a.b] = arr;).

2. Evaluator (virtlang-go/evaluator/)

  • evalVarDecl & evalVarAssignment Modifications:
    • These functions currently expect simple IdentifierNode or MemberExprNode for their Assignee. They would need to be updated to recognize and recursively process the new ObjectPattern or ArrayPattern nodes.
    • When an ObjectPattern is encountered, the right-hand side value must be validated to be an Object type. Then, iterate through the pattern's properties, extracting values from the source object and assigning them to the target variables (respecting renaming if present).
    • When an ArrayPattern is encountered, the right-hand side value must be validated to be an Array type. Then, iterate through the pattern's elements, extracting values by index and assigning them to the target variables (handling skipped elements and rest elements).
  • Runtime Value Handling: Ensure that values extracted during destructuring are correctly wrapped as *shared.RuntimeValue pointers for storage in the Environment.
  • Error Handling: Runtime errors for destructuring a non-object/non-array value, or for attempting to destructure nil where a value is expected.

3. Lexer (virtlang-go/lexer/)

  • No direct changes needed to the lexer.go itself, as all necessary tokens ({, }, [, ], ,, :, .) already exist. The parser will be responsible for interpreting these tokens in the context of destructuring.

Benefits

  • Readability: Simplifies code by making variable extraction more explicit and readable, especially for nested data structures.
  • Conciseness: Reduces boilerplate code, making scripts shorter and easier to maintain.
  • Developer Experience: Aligns VirtLang with modern language features, making it more intuitive for developers familiar with similar constructs in other languages.
  • Idiomatic Code: Enables more idiomatic patterns for handling data.

This feature would be a significant addition to VirtLang, greatly enhancing its expressiveness and usability. I'm keen to hear thoughts from the community on this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ASTThis is related to the AST (Abstract Syntax Tree)enhancementNew feature or requestevaluatorThis issue is related to the evaluatorparserThis issue is related to the parsersyntaxThis is related to the userland syntax.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions