Predicator.ContextLocation (predicator v3.5.0)
View SourceResolves location paths for assignment operations in SCXML datamodel expressions.
This module takes parsed AST nodes and extracts location paths that can be used for assignment operations. It validates that expressions represent assignable locations (l-values) rather than computed values.
Location Path Format
Location paths are returned as lists of keys/indices that represent the path to a specific location in the context data structure:
["user"]
- top-level variableuser
["user", "name"]
- property accessuser.name
["items", 0]
- array accessitems[0]
["user", "profile", "settings", "theme"]
- nested accessuser.profile.settings.theme
Assignable vs Non-Assignable
Assignable (valid locations):
- Simple identifiers:
user
- Property access:
user.name
,obj.prop
- Bracket access:
items[0]
,obj["key"]
- Mixed notation:
user.items[0].name
,data["users"][0]["profile"]
Non-Assignable (invalid locations):
- Literals:
42
,"string"
,true
- Function calls:
len(items)
,upper(name)
- Arithmetic expressions:
user.age + 1
,items[i + 1]
- Any computed values that can't be used as assignment targets
Examples
iex> alias Predicator.{ContextLocation, Lexer, Parser}
iex> {:ok, tokens} = Lexer.tokenize("user.name")
iex> {:ok, ast} = Parser.parse(tokens)
iex> ContextLocation.resolve(ast, %{"user" => %{"name" => "John"}})
{:ok, ["user", "name"]}
iex> {:ok, tokens} = Lexer.tokenize("items[0]")
iex> {:ok, ast} = Parser.parse(tokens)
iex> ContextLocation.resolve(ast, %{"items" => [1, 2, 3]})
{:ok, ["items", 0]}
Summary
Types
A location path representing the sequence of keys/indices to reach a location in the context.
Result of resolving a location expression.
Functions
Resolves an AST node to a location path for assignment operations.
Types
A location path representing the sequence of keys/indices to reach a location in the context.
String keys represent object properties, integer keys represent array indices.
@type location_result() :: {:ok, location_path()} | {:error, Predicator.Errors.LocationError.t()}
Result of resolving a location expression.
Returns either a successful path or a structured error explaining why the location is invalid.
Functions
@spec resolve(term(), Predicator.Types.context()) :: location_result()
Resolves an AST node to a location path for assignment operations.
Takes a parsed AST node and attempts to extract a valid location path. Validates that the expression represents an assignable location.
Parameters
ast_node
- The parsed AST node to resolvecontext
- The evaluation context (used for validating array bounds, etc.)
Returns
{:ok, path}
- A valid location path{:error, %LocationError{}}
- An error explaining why the location is invalid
Examples
# Simple identifier
resolve({:identifier, "user"}, %{})
#=> {:ok, ["user"]}
# Property access
resolve({:property_access, {:identifier, "user"}, "name"}, %{})
#=> {:ok, ["user", "name"]}
# Bracket access
resolve({:bracket_access, {:identifier, "items"}, {:literal, 0}}, %{})
#=> {:ok, ["items", 0]}
# Invalid: literal value
resolve({:literal, 42}, %{})
#=> {:error, %LocationError{type: :not_assignable, message: "Cannot assign to literal value"}}