Implemented in the maintained BASIL compiler. Values retain BASIL’s independent ownership semantics. This is not yet complete Python subscript compatibility; remaining boundaries are listed below.
Naming convention
| Operation | LIST | STRING |
|---|---|---|
| Sort in place | Sort(BYREF items[, Compare=comparator]) |
Use Sorted |
| Independent sorted result | Sorted(items[, Compare=comparator]) |
Sorted(text[, Compare=comparator]) |
| Reverse in place | Reverse(BYREF items) |
Use Reversed |
| Independent reversed result | Reversed(items) |
Reversed(text) |
Mutators return the existing INTEGER status 0. Value-returning forms leave their input unchanged. String operations use Unicode code points, preserving UTF-8; combining marks are separate elements. This convention is recorded in instructions.md .
Reads and slices
numbers=[0,1,2,3,4]
PRINT numbers[-1] ' 4
middle=numbers[1:4] ' [1,2,3]
backwards=numbers[::-1] ' [4,3,2,1,0]
everyOther=numbers[::2] ' [0,2,4]
PRINT "aé🌍"[-1] ' 🌍
PRINT "aé🌍"[::-1] ' 🌍éa[start:stop:step] uses Python’s half-open bounds, sign-dependent defaults,
negative indices, clipping and negative steps. A missing negative-step stop is
different from an explicit -1. Results are independent owned values, including
owned records/collections inside sliced lists. Indices/bounds/steps must be
INTEGER; existing 64-bit integer limits apply. Step zero raises SliceError
with Code 1. The implementation avoids overflow for minimum/maximum 64-bit bounds
and steps. Reads can chain through fields and other subscripts; temporaries are
kept alive until their dependent values are owned.
Subscript computation cannot leave the parent dangling. Named collection handles are refreshed after effectful index/bound evaluation: supported in-place growth and resize remain visible, atomic replacement selects the replacement, and an unrestored move of the parent is rejected. Already borrowed dynamic views protect their roots from invalidation; unnamed copyable parents use independent snapshots when needed. Failure/cancellation releases held owned parents and partial values.
Strings support reads and slices, not element/slice assignment. An invalid
STRING index raises checked IndexError; mutating STRING elements is rejected.
Existing dense ARRAY bounds and coordinate syntax are separate from LIST slices.
List slice assignment
numbers=[0,1,2,3,4]
numbers[1:4]=[8,9] ' [0,8,9,4]
numbers[::2]=[7,6] ' [7,8,6,4]
numbers[2:2]=[5] ' insert without removingA unit-step slice can grow or shrink. An extended slice requires exactly the
number of replacement elements selected; a mismatch raises SliceError Code 2
before mutation. RHS evaluation precedes slice-bound evaluation. Replacement
values are independent snapshots, including self-assignment and overlapping
slices. Nested record, list, dictionary and array destinations support the same syntax. Recoverable
validation failure leaves the destination unchanged; fatal allocation failure
retains the language’s separate fatal policy.
Dictionaries
DIM visits AS DICT OF STRING TO INTEGER=DICT()
visits["Ada"]=1
PRINT visits["Ada"]
PRINT SetDefault(BYREF visits,"Ada",99) ' 1; existing value retained
PRINT SetDefault(BYREF visits,"Bob",0) ' 0; missing key insertedDictionary brackets use the exact declared key/value types. Missing reads raise
checked MissingKey, and assignments insert or replace while retaining insertion
order. Copyable reads return independent values. Resource reads borrow checked
views; resource writes adopt fresh values or explicit TAKE and release any previous
owner. Resource Find returns an optional view; use Extract to remove ownership.
Resource views cannot outlive/invalidate their dictionary origin. SetDefault(table,key,fallback) eagerly
evaluates fallback like any ordinary argument, inserts it only when absent, and
returns the selected value independently. Zero, FALSE, empty strings and present
NONE are all existing values. With OPTIONAL dictionary values,
SetDefault(BYREF table,key) inserts NONE when absent. A statically nonoptional
value type needs an explicit fallback; no implicit NULL is introduced.
List/set conversions
SET(list) / ToSet(list) remove duplicates using existing hash/equality rules.
LIST(set) / ToList(set) return elements in the set’s deterministic insertion
order. Both return independent values. Same-kind conversions also copy
independently. LIST(text) splits into Unicode code points, and SET(text) keeps
unique code points in first-occurrence order. Unannotated empty constructors
still need enough type context to determine their element type.
Nested assignment and compound operators
See assignment rules for nested destinations, RHS-first ordinary assignment, single-evaluation compound updates and conservative borrow exclusions. A slice must be the final destination component. STRING mutation remains rejected.
Remaining compatibility blockers
- Direct LIST out-of-range access/element assignment retains the existing fatal
bounds policy. Converting this to checked
IndexErrorneeds a coordinated effect/FAILS migration, including the compiler itself and native exports. - Python’s dynamic typing, arbitrary-precision integers and shared mutable object aliases are not BASIL language semantics. No such behavior is silently added.