Documentation/Reference

Sequence operations and brackets

On this page

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 removing

A 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 inserted

Dictionary 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 IndexError needs 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.

From the BASIL documentation. View source ↗

Find your way around BASIL

Type to search the manual.