Variables, Constants, and Scopes - CPULL/Dflat GitHub Wiki

Variables and Type Inference

A variable name in Dflat must start with a letter and can be composed of letters, numbers, and underscores. They are case-sensitive, and cannot start with an underscore (_).

Dflat uses type-first declarations, but allows type inference when the compiler can deduce the type from the initializer.

  • Explicit declaration: i32 a = 10
  • Inferred declaration (var): var count = 10. The type is strictly taken from the initializer. If the compiler cannot decide the type, it results in a compile error (e.g., var x = null or var l = [] are invalid).
  • Partial inference: var can coexist with partial forms like arr a = [...], vec v = [...], or map m = {...}.

Multiple Assignments and Swaps

Dflat supports tuple destructuring and multi-variable assignments.

  • Multiple returns: a function can return more than one value:
i32 width, string name = getUser()
var userId, var userName = getUser()
existing, _, i32 fresh = f() // Mix existing, discard, new

To discard a value, you can use the discard operator (_).

  • Tuple destructuring: the items of a tuple can be unpacked into separate variables in one statement. Use _ to skip an item:
i32 total, string name, bool enabled = record
i32 onlyCount, _, bool onlyActive = record
  • Tuple item access: items can be read by name (record.label) or by index (record[1]). The index must be a literal, a const, or an enum value; an out-of-range index is a compile error. Indexes apply left to right (e.g., in an array of tuples, myTuple[2][1] is the second item of the third tuple).

  • Swapping: To swap two values:

x, y = y, x

The right side is evaluated first before any assignment occurs.

Constants

Constants are declared using the const keyword (e.g., const u64 SECRET_CODE_PHASE2 = 100). A const represents a read-only value and pointer, offering a global guarantee.

  • Naming rule: Constants declared with const must use UPPER_SNAKE_CASE; otherwise, a level 3 warning is emitted.

Scopes and Definite Assignment

Dflat uses C#-style block scoping, with specific rules for safety and initialization:

  • Block Scoping: Variables declared within a block are visible only within that block and its nested blocks.
  • Definite Assignment: Reading a variable before it is assigned on every execution path reads its zero value (null for objects) and triggers a level 1 warning.
  • No Shadowing of Locals: Declaring a local variable with the same name as a local variable in an enclosing block is a compile error.

Conversions

Dflat provides three main categories of conversion:

Cast (<type>)

Keeps the value. Out-of-range values saturate (triggering a level 2 warning), or raise an OutOfRangeCastException if a specific catch exists.

  • Real-to-integer conversions follow Rust rules: truncate toward zero, $+\infty \to \text{max}$, $-\infty \to \text{min}$ ($0$ for unsigned), and $\text{NaN} \to 0$.
  • Conversion to time: out-of-range values convert to null and raise OutOfRangeCastException if caught (silent).

Transmute ([type])

Reinterprets the exact same bits (zero-extends when widening).

  • [char]: an invalid code point maps to U+0000, or raises an InvalidCharacterCodePointException if a specific catch exists.
  • Pointers: Created from numbers or other pointers exclusively via transmute ([*u64]address), and such pointers are automatically marked as unsafe.

Implicit

Allowed only for widening conversions that keep the value within the same family (e.g., i8 -> i64, r32 -> r64), unsigned-to-wider-signed (u16 -> i32), any scalar type to bool, or any type to string (which calls toStr()). An implicit conversion is equivalent to a cast.

Casting and Transmuting to Boolean ([bool])

  • Numbers equal to 0 or NaN, '\0', null date/time/clock, zero/null lapse, null/empty string, and null evaluate to false.
  • Anything else evaluates to true.
  • Collections and tuples cannot be cast or transmuted to bool.
⚠️ **GitHub.com Fallback** ⚠️