On this page

Appendices

A. Language vocabulary

Keywords are case-insensitive. Canonical source uses lowercase. An indivisible multiword token uses snake_case; compositional grammar keeps independently meaningful words separate. end if is a closing keyword followed by a construct qualifier, not end_if. Escaped identifiers use @ where a name would otherwise conflict with language vocabulary.

The tables group vocabulary by its language role. A word's appearance in a contextual grammar does not make an arbitrary .NET member with that name a globally reserved keyword.

Area Canonical vocabulary
Source organization project, root_namespace, auto_import_directsharp, namespace, import, alias, Global, default_wrapper_engine
Types class, data, interface, enum, flags, class kind, inherits, exposes, implements, is, of, one of
Generic restrictions where with inherits, implements or the contextual phrase has constructor
Indexer property modifiers virtual, override, abstract on property [parameters]; action modifiers retain their own rules
Access and member modifiers public, private, protected, internal, static, readonly, abstract, overridable, overrides
Construction new, constructor, with, properties, fields, arguments, self
Actions and callables action, returns, return, yields, yield, from, call, async, await
Declarations and values let, let_if, outer, const, constants, nothing, default, true, false, lazy, as
Conditions and selection if, then, else, elseif, select, case
Enumeration for_each, in, where, consume, from
Ordinary loops for_each, range, to, step, where, order_by, skip, take, while, repeat, times, forever, until, continue
Loop exits break, continue, exit, for as the target in exit for; with name: identifier names an enclosing loop for break/continue
Statement destinations mark identifier, goto identifier
Exception handling try, catch, finally, throw, retry, try_get, LastAttempt
Contracts require, ensure, otherwise, result, old_value_of
Receiver and resource scopes use, use_if, using, take, dispose, block, end
Conversion and copying convert, tryconvert, conversions, implicit, from, to, copy_of
Concurrency concurrent, all, first, any, run, returns, limit, timeout, collects, collect, task_of, enter, leave, atomic
Events event, add_handler, remove_handler, raise_event, handles_event
Services needs, replaceable, services, provide, another, all, singleton, scoped, transient, key
Metadata attributes, assembly, description
Extension/adapters extension, feature, target, operation, calls, creates, sets, current, captured, expression, context, declares
Wrapper application wrap, engine
Boolean and numeric operators not, and, or, div, mod, checked, unchecked
Case-explicit equality eq_case_sensitive, not_eq_case_sensitive
Type/identity predicates is a, is exactly, is same_as and applicable is not forms
Absence/state predicates is nothing, is empty, is whitespace, is initialized, is working, is faulted and their negations
Text/pattern predicates ascii, numeric, integer, decimal, iso_date, containing, starting_with, ending_with, parsable_as, like, match and applicable _case_sensitive forms after is
Flag operations has_flag, has_not_flag, set_flag, clear_flag, toggle_flag
Compiler context __compiler__ and its compiler-defined members
Preprocessing #if, #elif, #else, #endif, #ifdef, #ifndef, #define, #define override, #undef, #include

Gate, IConsumable<T>, IConcurrentConsumable<T>, ILiveConsumable<T>, Consumables, ServiceProvider, ServiceScope, ServiceScopeFactory, MainServiceProvider, Chars, Unicode and ordinary type names such as String belong to type/library binding. GetService, RuleFor, NotEmpty, AddDbContext, WriteLine and SaveChangesAsync are APIs, not newly reserved language statements.

Retired forms must not be inferred from this inventory. Current source uses constructor rather than on create, for_each rather than for each, try_get rather than tryget, and contract otherwise rather than or throw. Core does not define deep_copy_of, has_any_flag, has_no_flag, is default, a validation keyword DSL, a project feature-activation block or a standalone generate construct.

B. Operator binding

Parentheses explicitly group expressions without changing once-only operand evaluation in source order. The following groups are ordered from highest to lowest binding:

Expression family Binding/associativity
Primary access/calls/indexing; postfix increment/decrement Forms a value before surrounding operations
Unary numeric +/-, complement ~, prefix increment/decrement, await Apply to their immediate operand; await requires an awaitable
*, /, div, mod Left-to-right
Binary +, - Left-to-right
Shifts <<, >>, >>> Left-to-right; supported operand types only
Relational <, <=, >, >=; all is/is not predicates Above equality, including identity, regex and like patterns
Equality =, <>, eq, not_eq and explicit case variants Left-to-right in expression context
Bitwise & Above bitwise ^
Bitwise ^ Above bitwise \|
Bitwise \| Above Boolean not
Boolean not Below comparisons/equality/predicates/bitwise; above and/or
Boolean and Left-to-right; short-circuit
Boolean or Left-to-right; short-circuit
?? Right-associative; short-circuit
Assignment/compound assignment statements Statement context only; chains use simple writable locals/parameters and right-to-left writes

convert operand to T consumes one immediate operand; its completed conversion binds strongly as defined in chapter 8. It does not absorb surrounding arithmetic without parentheses. Normal binary operators associate left-to-right unless specified otherwise; this table does not admit invalid operand types or general mathematical comparison chains. Predicate-local type/pattern grammar remains governed by its construct rules.

let total = convert (subtotal + tax) to Integer
let next = (convert amount to Integer) + 1
let eligible = not (balance > limit) and isActive

Composite conversion sources require parentheses. Bitwise/comparison/predicate combinations should use parentheses wherever grouping would otherwise obscure the intended operation. Assignment is a statement-context operation, not a freely nestable C-style assignment expression.

C. Predicate contracts

Predicate Accepted subject Meaning and important boundary
is nothing Absence-capable value Exact absence
is empty Applicable value/collection Absence, effective default where meaningful equality exists, or no sequence elements
is whitespace String Null/empty/whitespace test corresponding to IsNullOrWhiteSpace
is a T Runtime type-compatible subject Assignability and permitted flow narrowing
is exactly T Runtime-typed subject Exact runtime type rather than assignability
is same_as Reference subjects Reference identity rather than value equality
is in Applicable membership source Membership under the source's supported semantics
is like String or supported ordered/indexable sequence Wildcard/sequence pattern matching
is match String Ordinary .NET regex matching with default case policy
is initialized/working/faulted Language lazy value Nonforcing state inspection
has_flag/has_not_flag Flags enum Flag-condition presence or logical negation
is ascii String Characters/code units within ASCII range
is numeric/integer/decimal String Approved input shape plus finite Double/Long/Decimal range respectively; Boolean only
is iso_date String Narrow culture-independent valid yyyy-MM-dd calendar date
is containing/starting_with/ending_with String String relation with deterministic default case policy
is parsable_as T String with supported target parsing contract Boolean parse capability rather than a converted result

Scalar defaults count as empty: 0, false and Guid.Empty are examples. String absence and "" are empty; " " is not empty but is whitespace. A non-absent collection with zero items is empty without requiring equality to a particular empty collection object. Enumerable emptiness may probe enumeration; an efficient non-enumerating check is permitted where observably equivalent.

An ordinary reference type with no meaningful non-absent default/equality contract is empty only when absent. No structural equality is invented for this test. value = default is the contextual default comparison; is default is not a current predicate.

is not negates an applicable predicate. Explicit _case_sensitive String forms override the normal case-insensitive comparison for their operation; they do not change identifier binding. Built-in predicates are distinct from recognized Boolean Is*/Has* members, which still bind as normal APIs. Email, IBAN, JSON and telephone policies belong in libraries.

D. Conversion contracts

Source/target relationship Supported path Failure boundary
Identity/assignable value Ordinary assignability or convert Static incompatibility diagnosed
Runtime reference/interface Runtime compatible conversion tryconvert can report ordinary mismatch as absence
Valid boxing/unboxing CLR type rules Preserve runtime compatibility failures
Numeric conversion Applicable .NET-style conversion Narrowing warning; overflow follows checked policy
Nullable lifting/unwrapping Supported optional conversion Preserve absence; conversion does not imply default
String to recognized parse target Literal context or explicit conversion Invalid recognized literal diagnosed; runtime input can fail
String to one-String-constructor type Direct named-target construction User constructor executes at runtime
String to enum Case-insensitive declared name Unknown name is failure
Number to ordinary enum Value must identify declared member Undeclared value is failure
Number to flags enum In-range underlying bit pattern Preserve unknown bits; out-of-range is failure
Imported user conversion Actual CLR implicit/explicit operator Preserve its side effects and exceptions
Authored conversion One applicable from/to contract Ambiguous candidates diagnosed
Safe authored/recognized conversion tryconvert with genuine safe protocol Ordinary inability yields absence; unexpected exceptions propagate

A conversion selects one recognized step. It does not search A→B→C chains, serializers, TypeConverter, unrestricted reflection or arbitrary Convert.ChangeType fallbacks.

Target-typed String literals may initialize recognized targets or satisfy unambiguous parameters. An arbitrary runtime String does not implicitly parse merely because assignment has a target type: use text as T or convert text to T. One accessible exactly-one-String constructor can participate in direct construction; compiler selection does not execute that user constructor during compilation.

Explicit target-typed fractional-to-integral narrowing truncates toward zero and warns about possible loss. This does not silently add lossy conversions to unrelated overload resolution. Untargeted fractional literals infer Decimal. Integer-operand / yields a fractional Double result; div truncates its quotient toward zero.

tryconvert is not try_get convert: the former requires a real safe protocol; the latter explicitly catches normally catchable computation failures. Ordinary culture-stable conversions use recognized deterministic contracts. Explicit .NET Parse/TryParse APIs remain available for application-specific culture, styles and format policy.

E. Construct grammar summary

These shapes describe already-defined constructs. Brackets denote optional grammar, braces repeated grammar and capitalized labels syntactic categories. They are notation rather than literal DirectSharp source.

Project       := project { ProjectSetting } end project
AutoImport    := auto_import_directsharp (true | false)
Action        := [Access] [async] action Name(Parameters)
                 [returns Type | yields Type] Body end action
Await         := await UnaryExpression
TaskCapture   := task_of(Expression)
Constructor   := [Access] constructor(Parameters) Body end constructor
Class         := [Access] class Name [GenericParameters] [ClassHeader]
                 { Member } end class
InterfaceBody := implements Interface { Member } end implements
ClassKind     := [Access] class kind Name [GenericParameters]
                 { KindContribution } end class kind
Extension     := extension Type { ExtensionAction } end extension
If            := if Condition then Body { elseif Condition then Body }
                 [else Body] end if
Enumeration   := [concurrent] for_each Binding in Source [LoopInputs]
                 Body end for_each
Consumption   := [concurrent] consume Binding from Source [LoopInputs]
                 Body end consume
Concurrent    := concurrent (all | first | any) [PublishedResults]
                 [with Inputs] Body end concurrent
RunCall       := [ResultBinding =] run Invocation
RunBlock      := [ResultBinding =] run Body end run
GateRegion    := enter Expression [with Inputs] Body leave
AtomicRegion  := atomic Body end atomic
AtomicSwap    := atomic swap(Location, Location)
Extraction    := let from Expression { ExtractionLocal } end let
ConditionalExtraction := let_if from Expression { ExtractionLocal } end let_if
ExtractionLocal := Identifier [ as Type ] = Expression
Needs         := needs { NeedDeclaration } end needs
Services      := services Name [Parameters] Body end services
Using         := using ResourceDeclarations Body end using
Use           := (use | use_if) Expression [Refinement] Body end (use | use_if)
TryGet        := try_get Expression | try_get Body take Expression end try_get
Metadata      := attributes AttributeList | attributes { Attribute } end attributes
Description   := description String

Full type/member/pattern/parameter rules in the chapters constrain these shapes. The notation does not permit every combination mechanically: resource ownership, async ABI, legal attributes, constructor placement and supported concurrent sources still apply. Qualified endings verify the construct they close. Keyword normalization does not fuse closing qualifiers.

An applicable generic declaration places its parameter list after the declaration name and its restrictions in the header. The Action shape above is the nongeneric case; generic actions use that same callable/result model with these additional pieces:

GenericParameters := < of Identifier { , Identifier } >
GenericArguments  := < of Type { , Type } >
GenericConstraint := where Identifier
                     ( inherits Type | implements Type | has constructor )

These angle brackets are literal delimiters in the source. Commas separate parameters/arguments; each nested constructed type has its own list. Chapter 4 defines the legal CLR restriction boundary, and the generic reference shows complete declarations.

F. Required diagnostic conditions

The specification names conditions rather than inventing implementation diagnostic numbers.

Area Required diagnostic examples
Lexical/names Invalid identifiers; case-insensitive duplicate symbols; mismatched endings
Declarations Uninitialized ordinary local; duplicate effective project; illegal access/modifier
Binding/types Inaccessible member; ambiguous import/overload/conversion; violated generic constraints
Values Writable operation on readonly/lazy storage; unsupported implicit runtime String conversion
Selection/contracts Missing expression result path; invalid take; invalid snapshot source
Construction Abstract construction; inaccessible constructor; missing required need
Resources Ownership-taking disposal of known borrowed needs/services
Async Fresh awaitable call without await/task_of/run; suspension in a fixed synchronous contract; unavailable Cancellation; incompatible imported contract
Async warnings Locally provable captured-operation abandonment; capture-only try/catch does not observe later failure
Concurrency Nonpositive limit; statically producer-free first/any; premature result use; return across an iteration boundary; provable shared write; run without an owner; missing/incompatible inline branch result; control transfer out of a run body
Atomic Unsupported atomic operation; explicit/implicit suspension in atomic block
Consumption Unsupported source; raw database-reader concurrent consume
Events Incompatible handler; external raise; untrackable declarative event source
Services Invalid key match; dependency cycle; singleton path to scoped service
Metadata Invalid attribute target/arguments; declaration metadata on unsupported item
Features Unavailable feature/library; conflicting feature names; forbidden generation
Wrappers Missing/unknown engine; unsupported target; recursion; invalid expansion/name collision
Preprocessing Undefined live substitution; conflicting definition; missing/non-replaceable override target; malformed include literal; include cycle/path escape

Warnings/analyzers address cases that cannot be statically proved, such as imported aliases hiding shared mutation or opaque registration graphs. A diagnostic must explain the actionable source condition and preserve relevant DirectSharp locations. Backend compilation success does not excuse accepting a source program whose language contract requires rejection.

G. Library contracts referenced by the language

The language's required library relationships are distinct from grammar and from optional conveniences.

Contract Required behavior
Gate Named async-capable capacity; structured acquisition/release; acquisition timeout
IConsumable<T> / ConsumeResult<T> Awaitable acquisition with item presence separate from normal completion; failures propagate
IConcurrentConsumable<T> Custom source capability for overlapping acquisition and valid acquired items, without blanket payload thread safety
Reader adapters Ephemeral current record, current-result-set-only consumption, no concurrent raw cursor
Service provider/scope/factory Explicit scopes, required/eager multiple retrieval, exact non-null keys, borrowed ownership
ServiceNotFoundException Missing required registration; InvalidOperationException subclass with requested ServiceType and exact nullable ServiceKey
Lazy runtime support Once-only safe publication, cached absence/failure, nonforcing state, recursion detection
Concurrent result support Structured ownership, whole-iteration limits, ordered publication and producer identity
Text/conversion support Deterministic language formatting/parsing contracts and normal CLR interoperability
Source/diagnostic support Source correlation through includes and expanded programs

Application-facing APIs use the DirectSharp namespace. The implementation is largely C#/.NET and may use a small required runtime assembly. The language does not prescribe an invented final interface signature for every helper: an API must implement the observable contract while preserving ordinary .NET compatibility. Optional mapping, serialization, copying and framework adapters remain separate packages/capabilities.

H. Version and backend scope

This specification describes the DirectSharp v1.0 core design and its initial .NET/C# backend relationship. The language semantics are independent of a particular SDK, runtime release or editor.

Source semantics, CLR representation and compiler/runtime package versions are separate compatibility concerns. A reference C# example illustrates semantics within its shown context; it is not a universal promise about all historical .NET targets. Imported libraries keep their own versioned API contracts. Optional libraries/features do not become core language guarantees merely by being available through a reference.


Specification contents · Previous: 28. Reference C# lowering