Conversation
Convert Rhai arrays and object maps recursively into pod2 Array and Dictionary values, and add set_of for constructing Sets. Reject variables inside container literals because their values are unavailable during Load. Render supported containers as Podlang literals, falling back to commitments when no literal representation exists. Add dict_get and array_get to bind entries with containment statements. Keys may be variables, allowing a literal container to serve as a lookup table and its returned dictionary fields to be read directly.
Register variables returned by SDK methods as soon as they are created, so callers can use them inline without first binding them with var. Rename generated variables in place when a script assigns a name, preserving wildcard order. Treat var bindings of literal values like ordinary Rhai bindings instead of creating wildcards. Route ArgHandle.get through dict_get and report invalid literal field access as a script error rather than panicking.
Statement and Intro instructions retained mutable references to their arguments, so later object updates changed the values used during replay. Capture OperationArg values when each instruction is recorded and replay those snapshots during proof construction. This keeps containment statements and their bound values aligned with the pre-update object state.
Check known container kinds and array index types during Load, and resolve fully literal lookups immediately. This prevents kind mismatches and missing rows from producing invalid predicates. Validate field access whenever the value is available and return script errors instead of panicking. Also promote Rhai booleans to pod2 integer values in container literals.
Container kind metadata may identify the same raw value as multiple container kinds. Render a literal only when its kind is unambiguous; otherwise render its commitment. This prevents nested container text from claiming the wrong kind while preserving the raw value used by the verifier.
Reuse shared helpers for Rhai array conversion and Ref extraction instead of repeating dynamic-value promotion paths. Update the SDK documentation and tests to cover variable container lookups, named literals, boolean elements, and ambiguous container rendering.
Set and Update instructions retained mutable references to written values, allowing later object mutations to change the values replayed during proof construction. Capture OperationArg values when each write is recorded. Reuse the shared literal-entry resolver and remove redundant work from literal container lookups.
set_of constructs a value and does not access action state. Register it as a free Rhai function and return the pod2 Set directly, allowing helper functions to build Set-containing tables without receiving action. Register the Set type name for clearer Rhai errors and keep invalid field access on Set values as a script error.
Add string validation for dictionary keys while retaining integer validation for array indexes. Represent lookup kinds explicitly so Load reports container and key errors before generating predicates. For raw values accepted as multiple container kinds, render the first supported form in deterministic order: set, dictionary, then array. Continue using commitments for sparse arrays. Refresh the SDK documentation and tests to match these rules.
Add a compact plugin demonstrating literal containers, variable-key lookups, native statements, witness arithmetic, state-header access, subactions, and object field reads. Document how authenticated data can select table rows while player-selected choices remain separate actions. Include the generated Podlang and current planner limitations.
ed255
left a comment
There was a problem hiding this comment.
LGTM! I've left a few small comments
| /// prefer set, then dictionary, then array. Each representation has the same | ||
| /// raw value, which is what statement arguments use. | ||
| /// | ||
| /// Podlang cannot represent sparse arrays, so they are rendered as their |
| write!(f, "{sep}{}", LiteralFmt(element))?; | ||
| } | ||
| return write!(f, "]"); | ||
| } |
There was a problem hiding this comment.
I think you should add an else here with a warning or an error, or a panic. Otherwise if an array with gaps arrives here, it won't be rendered, silently.
| assert!(err.contains("is a var, not a literal"), "{err}"); | ||
| } | ||
|
|
||
| /// Renders sparse arrays as commitments because Podlang has no sparse-array |
|
|
||
| fn RevealChart(action) { | ||
| var chart = action.mutate("Chart"); | ||
| chart.update("x", action.array_get([10, 20, 30], chart.code)); |
There was a problem hiding this comment.
Interesting, I guess this is assigned to an anonymous wildcard internally?
There was a problem hiding this comment.
The answer is yes! Now the sdk creates anonymous wildcards automatically, and they are prefixed with _. On assignment they are renamed to whatever the script says via var foo = ...
| for var in self.vars.iter_mut().filter(|v| v.as_str() == old) { | ||
| *var = new.clone(); | ||
| } |
There was a problem hiding this comment.
we should expect to find old only once. What about making it more clear like this?
let old_var = self.vars.iter_mut.find(|v| v.as_str() == old).expect("old exists");
*old_var = new.clone();
| let mut ctx = arg_ctx.ctx.0.borrow_mut(); | ||
| // Preserve a generated variable's identity and wildcard | ||
| // position when the script assigns it a name. | ||
| if is_anon_var(&old_name) { |
There was a problem hiding this comment.
my understanding of the code is that if a user defines a var _foo then a o reassign it would be detected as anon var and renamed?
There was a comment in is_anon_var related to this that I didn't fully understand:
/// Script-provided names may also begin with this prefix. Treating them as
/// generated allows a subsequent binding to rename the handle instead of
/// creating an alias.
The comment explains this behavior as a feature, but it seems more like a side effect? Would you say it's advisable for users to not prefix a var with _?
This adds first-class container literals and variable-key lookups to the SDK, making it practical to represent lookup tables directly in Rhai scripts.
Rhai arrays and maps now convert recursively to pod2 Arrays and Dictionaries, while the new free-standing set_of function constructs Sets. Scripts can query these containers with
array_get,dict_get, orobj.get, including when the key is a variable.Key changes
nanoverseexample plugin to demonstrate lookup tables, witness arithmetic, state-header access, subactions, and related SDK features.These changes let authenticated object data select rows from literal tables without requiring a separate action for every row. Player-selected choices can remain separate actions, while data-selected behavior can be expressed compactly through constrained lookups.