Sample build and verification details
These repository guides record commands, prerequisites, implementation limits and verification evidence for the sample sources. They are operational documentation, separate from the language examples. Requirements describe these build configurations, not the DirectSharp language.
AsyncReports
Source: Async report with owned resources
This application compiles actual DirectSharp source against framework APIs. Its DirectSharp ReportSession class owns a MemoryStream, reads through value-form using over a StreamReader, and supplies an authored async dispose block. The program owns the session through lexical let using, awaits its Read action with the forwarded contextual cancellation token, and checks its normal result contract. All session behavior is compiled from ReportSession.ds; no handwritten C# application implementation is involved.
From the compiler directory:
dotnet run --project DirectSharp.Compiler -- run ../samples/AsyncReports/*.ds --entry Program.Run
Expected output:
DirectSharp async report
The reader is constructed with leaveOpen enabled: it is cleaned up after capturing the text, while the session retains its stream until its own asynchronous disposal. A canceled read still cleans up its acquired reader. The session exposes IAsyncDisposable without a synchronous blocking bridge; repeat successful disposal is harmless.
The CLI waits for the asynchronous entry action, including its cleanup, and returns a failure exit code for asynchronous exceptions. This explicit async action has the normal optional cancellation contract. Ordinary inferred async actions do not gain a cancellation parameter. Each resource uses the cleanup interface exposed by its static type; cleanup completes in reverse acquisition order before the normal postcondition/result is published.
The compiler uses the current .NET 8 bootstrap. This sample does not claim structured concurrency, background scheduling or other framework versions.
Automated compiler cases execute this source for successful and repeated reads, repeated disposal, failed reading after disposal, and an explicitly canceled read. The post-disposal failure comes from the ordinary StreamReader constructor, which rejects an unreadable stream.
ChannelReports
Source: Process queued reports with .NET Channels
This application compiles three actual DirectSharp files. ReportJob is an ordinary class with a required name. ReportWorker.Reports is an authored async iterator: it consumes a ChannelReader<ReportJob>, awaits each report operation and yields the completed name. Process consumes that stream and collects the names. Program starts the worker with task_of while the queue is empty, writes two jobs, completes the writer and awaits the worker. All application behavior is compiled from DirectSharp; Channels is the ordinary .NET library.
From the repository's compiler directory, using the .NET 8 bootstrap:
dotnet run --project DirectSharp.Compiler -- run ../samples/ChannelReports/*.ds --entry Program.Run
dotnet run --project DirectSharp.Compiler -- transpile ../samples/ChannelReports/*.ds -o /tmp/ChannelReports.cs
dotnet run --project DirectSharp.Compiler -- build ../samples/ChannelReports/*.ds -o /tmp/ChannelReports.dll
Expected console output:
Processed: DAILY SALES, OVERDUE INVOICES
ReportWorker.Reports declares async action ... yields String and uses ordinary ReadAllAsync(Cancellation.Token). Calling Reports obtains an IAsyncEnumerable<String> directly; it requires neither task_of nor await. Its body, including its require check, runs during enumeration. Process remains a normal Task-returning async action, so Program captures that operation with task_of and later awaits it. The loop selects async enumeration from IAsyncEnumerable<ReportJob>; each body finishes before the next item, including its explicit await. Generated C# uses native await foreach and awaits enumerator cleanup on every exit. This is a single consumer processing items sequentially. Task capture starts the operation according to its normal contract; it does not schedule a new background thread or create an owned concurrency scope.
Process, Reports and First declare explicit async contracts with the standard optional cancellation token. Reports also emits standard EnumeratorCancellation metadata, allowing a consumer to supply a token when enumeration starts. Distinct call-time and enumeration-time tokens combine through native .NET iterator rules. Program.Run forwards its current token to Process. ReadAllAsync receives that token explicitly; enumeration also forwards the recognized context to the standard enumerator protocol. An ordinary action can infer async from for_each without declaring async, but inference supplies no Cancellation context or extra token parameter. Use an explicit token with WithCancellation when configuring an otherwise unconfigured source; a standard configured wrapper retains its own token and continuation choices.
The compiler suite executes the same source files for these cases:
| Entry | Observable behavior |
|---|---|
| Program.Run | An empty open queue leaves the captured worker incomplete; two jobs produce the expected summary after writer completion. |
| Program.CancelWaiting | Canceling the worker while it awaits an item produces OperationCanceledException; the shared channel remains writable. |
| Program.EarlyExit | Returning from the first iteration releases the enumerator without closing the channel; the next reader receives the second job. |
| Program.SourceFailure | A writer's failure reaches the consumer as the original FormatException instance. |
The last three entries return values checked by the test runner rather than printing output. Canceling or disposing a consumer does not complete a writer it does not own. ReadAllAsync follows its native cancellation contract; cancellation is cooperative and does not promise to discard items already available.
See CS-ITERATOR-004, CS-ENUMERATION-001 and the compiler coverage. Concurrent worker groups and Gate require further compiler/runtime implementation; this application demonstrates authored async production and ordinary consumption without approximating those constructs.
CreditAccount
Source: Credit-account example
CreditAccount.ds is a small companion to the repository README’s order-approval workflow. Program.ds constructs an account with a credit limit of 100, attempts three charges, and prints the outcomes through ordinary .NET Console calls. The business logic is DirectSharp source.
From the repository root, with the .NET 8 SDK installed:
dotnet run --project compiler/DirectSharp.Compiler -- run samples/CreditAccount/*.ds --entry Program.Run
Expected output:
Charge 75: True
Charge 25: True
Charge 1: False
Balance: 100
The shell expands *.ds. On a shell without expansion, list samples/CreditAccount/CreditAccount.ds and samples/CreditAccount/Program.ds explicitly.
The constructor accepts a nonnegative Decimal limit and initializes the readonly property once. The balance starts at zero and has a private setter. TryCharge rejects zero/negative amounts through its entry contract. It calculates available credit, declines amounts above that value, and updates the balance only for an approved charge. A charge exactly equal to the available credit succeeds. Its postcondition also applies to the early declining return. Checking against remaining credit before adding avoids overflowing Decimal merely to decide that an oversized charge should be declined.
To inspect the generated C# or emit a CLR library assembly:
dotnet run --project compiler/DirectSharp.Compiler -- transpile samples/CreditAccount/*.ds -o /tmp/CreditAccount.cs
dotnet run --project compiler/DirectSharp.Compiler -- build samples/CreditAccount/*.ds -o /tmp/CreditAccount.dll
Choose suitable output paths on Windows. For a larger application, continue with the Customer sample.
CustomerApplication/FluentValidation
Source: Customer application with FluentValidation
This variant compiles the shared Customer model and these three replacement files: CustomerValidator.ds, CustomerService.ds and Program.ds. Validation rules, registration, lookup and failure handling are DirectSharp source. The validator inherits the real FluentValidation AbstractValidator<Customer> and uses ordinary RuleFor, NotEmpty, Length and EmailAddress APIs. The service calls ValidateAndThrow before storing a customer.
From the repository's compiler directory, restore the pinned test dependency and run:
dotnet build DirectSharp.Compiler.Tests
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/Customer.ds ../samples/CustomerApplication/FluentValidation/*.ds --reference DirectSharp.Compiler.Tests/bin/Debug/net8.0/references/FluentValidation.dll --entry Program.Run
Expected output is Ana Petrova: 1 customer. List the three replacement files explicitly if your shell does not expand wildcards. The same source/reference arguments work with check, transpile and build; transpile exposes the generated C# and private expression-tree lowering helpers.
To let the SDK restore/select package dependencies instead of taking a DLL from the test output, replace the --reference option and its DLL path with --project ../compiler/fixtures/samples/ExternalValidation/Dependencies.csproj. The included dependency context contains only ordinary SDK/package configuration. The DirectSharp model, validator and service remain the same actual .ds inputs. See the current SDK context limits.
The original four-file contract-based variant remains runnable without an external dependency. Do not compile both variants' validator/service/program declarations together: their class names intentionally match.
DirectSharp's absence-preserving selectors lower to CLR block expressions with temporary receivers. Those trees retain getter order, once-only evaluation and absence semantics. FluentValidation cannot extract a simple member path from a block, so each rule explicitly calls its normal OverridePropertyName API. This preserves Name and Email in validation errors without changing language reads or adding a compiler-specific validation transformation. Other expression-tree consumers must support the emitted CLR nodes; remote query-provider translation is not verified.
The executed CustomerFluentValidation conformance cases check success, invalid email, the Email failure name, zero stored customers after rejection, duplicate rejection and missing lookup. InvalidEmail raises FluentValidation.ValidationException; the service's duplicate rule raises InvalidOperationException. This sample uses in-memory storage and is not a production persistence or concurrency implementation.
CustomerApplication
Source: Executable Customer application
Customer.ds, CustomerValidator.ds, CustomerService.ds and Program.ds contain the core application logic compiled by DirectSharp. Customers start inactive, as in the larger walkthrough. This small slice uses caller-supplied Integer IDs to exercise readonly constructor assignment; the full service design assigns Guid identifiers during registration. They create and update customers, validate inputs, approve credit, keep an in-memory List<Customer>, reject duplicate email addresses and look up customers using case-insensitive language String equality.
Customer.ds also declares ICustomerDetails, a getter-only view of Id, Name and Email. The model maps its properties explicitly, and both application variants read the summary through that interface. The view still refers to the live customer: renaming the customer changes the Name observed through it. Getter-only access does not freeze the object or prevent changes through its ordinary class API.
CustomerService.TotalCreditLimit aggregates registered customers through ordinary LINQ Sum(.CreditLimit). This is a compiled DirectSharp selector and normal .NET overload binding. Property reads retain their nullable value result, so the action coalesces the sum to zero. Both application variants test two approved limits totaling 350, and their main entry verifies its customer's approved limit.
From compiler/, with the .NET 8 SDK installed:
dotnet run --project DirectSharp.Compiler -- check ../samples/CustomerApplication/*.ds
dotnet run --project DirectSharp.Compiler -- transpile ../samples/CustomerApplication/*.ds -o /tmp/CustomerApplication.cs
dotnet run --project DirectSharp.Compiler -- build ../samples/CustomerApplication/*.ds -o /tmp/CustomerApplication.dll
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/*.ds --entry Program.Run
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/*.ds --entry Program.ImportText
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/*.ds --entry Program.ImportRecord
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/*.ds --entry Program.ReplaceCustomer
dotnet run --project DirectSharp.Compiler -- run ../samples/CustomerApplication/*.ds --entry Program.SummarizeCustomers
The shell expands *.ds; on a shell without expansion, list Customer.ds, CustomerValidator.ds, CustomerService.ds and Program.ds explicitly with their paths. Choose appropriate output paths on Windows.
Expected output:
Ana Petrova: 1 customer
Run is an ordinary static action selected by the CLI's --entry option. It is not a special language entry-point name. build emits a CLR library assembly for a host to call; it does not create an application host or a project file. run executes compiled source in the CLI process and does not print return values automatically.
ImportText prints Imported: Ana <ana@example.com>. CustomerService.RegisterText accepts a name line and an email line, trims both, and rejects additional lines. It passes a value-form using directly to Register: the StringReader is cleaned up after constructing the candidate and before registration runs. The Customer constructor and ordinary validator enforce their existing rules. Separate execution cases verify that extra input or invalid email leaves storage empty. This is a small text-import format, not CSV or a persistence API.
ImportRecord prints Imported record: Ana <ana@example.com>. This format adds an Integer ID line before the name and email. The ordinary Customer(record as String) constructor reads and validates the three lines in a value-form using on the right of self.Id = .... It initializes Name and Email, captures the parsed ID, disposes the StringReader, and then assigns readonly Id exactly once. Missing or extra lines, invalid/overflowing/nonpositive IDs and empty names/emails fail construction. Invalid email is rejected by the service's ordinary validator. The failed record never reaches storage; this does not promise rollback of arbitrary constructor effects or automatic cleanup of a partially constructed object. Only the lexically owned reader is disposed.
ReplaceCustomer prints Replaced: Ana Petrova. CustomerService.ReplaceAt validates the candidate, reads the selected List entry, rejects an email owned by a different registered customer, and replaces that indexed entry. Its postcondition checks that the exact replacement is stored. Invalid candidates or duplicate email leave storage unchanged; an invalid position propagates the ordinary List ArgumentOutOfRangeException. These operations use normal .NET indexing and DirectSharp business logic, with no custom collection adapter.
SummarizeCustomers prints Portfolio: 2 customers, 1 active, 1 inactive. Customer.IncreaseLimit uses a guarded Decimal += update; the entry checks that two increases total 75. CustomerService.CountByActiveStatus groups customers in an ordinary Dictionary<Boolean,Integer>, initializing a missing count with counts[active] ??= 0 before incrementing it with += 1. Present zero and false are values, so dictionary coalescing tests key presence rather than treating either as absence. A separate execution case counts two inactive customers to verify accumulation. No C# business-logic helper is involved, and these ordinary dictionary operations provide no atomicity guarantee.
CustomerValidator currently uses fail-fast native contracts. It is not FluentValidation support and does not accumulate validation errors. The complete Customer walkthrough describes the larger intended application. The FluentValidation variant now compiles ordinary library rules and ValidateAndThrow against the same Customer model. Select that variant explicitly; its files replace this directory's validator, service and program.
The conformance catalogue exercises successful registration, invalid email, duplicate email, invalid credit, missing lookup and a live interface view. A negative source case rejects assignment through the getter-only interface. The compiler test runner builds these exact four files and invokes the resulting assembly. Business logic is not supplied by a C# substitute. This small application has no persistence, concurrent mutation guarantee or production email-validation policy.
Selective asynchronous HTTP lookup
RemoteCustomerLookup.ds is an additional ordinary instance class. Its constructor borrows an HttpClient whose BaseAddress is configured by the caller. ReadDisplayName requires a positive Customer ID, requests customers//display-name with the action's cancellation token, and returns the response text. A typed when filter returns nothing only for HTTP 404; HTTP 500, original transport failures and cancellation propagate. The lookup does not dispose its injected client.
The existing wildcard check/transpile/build commands include this file. The core Program entries do not contact a server. The compiler test runner compiles the lookup separately and executes its actual DirectSharp logic with native HttpMessageHandler response fixtures, covering success, 404/500, original connection failure, cancellation, input guards and client reuse. No network request is sent by these tests and no C# replacement implements the lookup policy.
Credit-limit input errors
CreditLimitInput.ds parses a nonnegative Decimal using invariant culture. Its grouped FormatException/OverflowException handler translates malformed and oversized text into an ArgumentException attributed to text, preserving the native failure as InnerException. Negative values retain ArgumentOutOfRangeException; absent input retains ArgumentNullException. The shared handler uses the common Exception view rather than assuming either constituent type.
From the repository root, run the actual source with:
dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CreditLimitInput.ds --entry CreditLimitInputExample.Run
It prints Parsed credit limit: 250.50. Compiler catalogue cases execute valid/zero inputs, absent/negative values, malformed input, Decimal overflow and preservation of the original inner exception. The example performs no storage update or hidden retry.
Explicit bounded HTTP retry
RetryingCustomerLookup.ds is a separate lookup variant using ordinary HttpClient. ReadDisplayName(customerId, maximumAttempts) retries GET only when its typed filter identifies HTTP 503. LastAttempt.Number supplies the completed attempt number, and the handler explicitly compares it with the caller's positive maximum before retrying. HTTP 404 returns nothing. Exhausted 503, HTTP 500, unrelated transport failures and native cancellation propagate. There is no implicit backoff or retry policy.
The action checks Cancellation before each request and forwards Cancellation.Token to HttpClient. It borrows the injected client and does not dispose it. The existing wildcard compilation includes this source; the Program entries still execute without network access. Native transport fixtures execute the compiled DirectSharp policy for 503/503/success, maximums of one and three, 404/500, original transport failures, cancellation between attempts, input contracts and client reuse. These tests send no network requests.
Optional import configuration
CustomerImportOptions.ds demonstrates explicit best-effort acquisition. PortOrDefault uses inline try_get around Integer parsing, with a 443 fallback outside protection. Parsed ports outside 1–65535 remain argument errors rather than silently becoming a default. TryReadPort checks its path argument, opens an ordinary StreamReader in multiline try_get, parses and validates its contents, captures the final take value and closes the owned reader. Missing/unreadable/invalid files produce nothing under this optional-file policy; it adds no logging or retry. LastAttempt is lexical metadata inside the executing action, not a caller-visible global record.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CustomerImportOptions.ds --entry CustomerImportOptionsExample.Run
It prints Customer import port: 443. The compiler suite executes the exact source for valid/invalid/absent/overflow text, range errors, real valid/invalid/missing files, a missing path argument and reader release. The existing Customer wildcard commands include this additional source.
Missing customer notes with handlers first
CustomerNoteReader.ds puts its missing-file policy at the start of the try: FileNotFoundException and DirectoryNotFoundException share a handler returning nothing, followed by end catch. The protected body then opens an ordinary StreamReader, reads/trims the note and closes the owned reader before returning. Successful empty text remains an empty String. Other file/access failures propagate, and the path contract runs before protected work. Declaring handlers first does not execute them on entry or give them access to body-only locals.
Run the actual source from the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CustomerNoteReader.ds --entry CustomerNoteReaderExample.Run
It prints Customer note: Call Ana before delivery.. The example creates a unique directory under the system temporary directory, writes its sample note and removes the directory in finally. Compiler tests also supply real files and verify text/empty results, reader release, missing files/directories, the missing-path guard and propagation of unrelated native file errors. All selection and reading logic is compiled from DirectSharp source.
Readonly import settings
CustomerImportSettings.ds moves optional port acquisition into an ordinary constructor. The readonly Port is assigned from try_get Integer.Parse(text) ?? 443; range validation then rejects parsed values outside 1–65535. Suppressing parse failure does not suppress that guard or bypass readonly initialization. Absent, malformed and overflowing text use the fallback; zero and out-of-range parsed ports remain errors.
From the repository root, run dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CustomerImportSettings.ds --entry CustomerImportSettingsExample.Run. It prints Customer import settings: port 443. Compiler tests execute that source for valid/boundary/defaulted ports and range exceptions. The Customer wildcard commands include the settings class.
Required settings with bounded provider retry
CustomerPortSettings.ds borrows an ordinary Func<String,String> provider for CustomerImportPort. Its constructor retries only TimeoutException, up to the caller’s positive maximumAttempts, using LastAttempt.Number. It parses and validates the result, then assigns readonly Port and Attempts. Parsing, range, unrelated provider errors and cancellation propagate; there is no fallback, automatic delay or provider ownership. The constructor returns no usable settings object when acquisition or validation fails.
From the repository root, run dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CustomerPortSettings.ds --entry CustomerPortSettingsExample.Run. It prints Customer port: 8080 after 1 attempt. Compiler tests execute the actual source with native provider callbacks for two timeouts followed by success, ceilings of one and three, input/range boundaries, original exceptions and cancellation. Those callbacks supply dependency outcomes; the retry and validation policy is DirectSharp code.
Customer contact accessors
CustomerContact.ds validates and trims Name in an ordinary setter, then changes its private backing storage and increments a private counter. DisplayName and ChangeCount are computed getters. An invalid name throws before those changes; the getter methods do not create additional stored properties. External access uses ordinary CLR properties, including serialization and the optional empty-parentheses getter spelling.
From the repository root, run dotnet run --project compiler/DirectSharp.Compiler -- run samples/CustomerApplication/CustomerContact.ds --entry CustomerContactExample.Run. It prints Ana Petrova | ANA PETROVA | 2. Compiler tests execute the source, verify absent/blank input failures and retained state, and serialize the result through ordinary System.Text.Json. The Customer wildcard commands include this class.
CustomerCreditImport
Source: Customer credit import with row error handling
This application reads one credit limit per line using ordinary .NET Decimal.Parse, CultureInfo.InvariantCulture and StringReader APIs. All parsing, validation, row classification and totals are written in DirectSharp .ds files.
A malformed, overflowing or negative amount produces a rejected CustomerCreditRow from its typed catch handler. Its CreditLimit is nothing and Error explains the failure. A valid zero remains an accepted zero. After the consumer requests another item, the iterator resumes and reads the next line; input is not counted or buffered in advance.
From the repository root, with the .NET 8 SDK installed:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/CustomerCreditImport/*.ds
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.Preview
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.StrictRun
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.DelimitedRun
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.RejectStrict
The five entries print:
Credit import: 2 accepted; 3 rejected; total: 375.50
Line 1: Credit limit must be a decimal number
Strict credit import: 3 accepted; total: 375.50
Delimited credit import: 3 accepted; total: 375.50
Strict credit import rejected; existing rows retained
Run materializes five rows through ordinary LINQ ToList, then totals accepted amounts. Preview stops after the first rejection; disposing the suspended enumerator closes the owned reader without reading the remaining input. The importer catches only the three expected input failures. Unexpected failures propagate, and the ordinary resource lifetime still closes the reader.
The record retains its one-based line number and an absent amount for rejected input. This example imports individual credit limits rather than changing customer accounts. A production importer can associate each row with a customer ID and apply its persistence and authorization policies separately.
Inspect the generated C# or emit a CLR assembly:
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerCreditImport/*.ds -o /tmp/CustomerCreditImport.cs
dotnet run --project compiler/DirectSharp.Compiler -- build compiler/fixtures/samples/CustomerCreditImport/*.ds -o /tmp/CustomerCreditImport.dll
The importer yields an accepted row directly inside try, after parsing and validation. Its typed catches yield rejected rows. The compiler evaluates each row under native ordered catches, then publishes it outside that C# try/catch region; selected handlers run in a separate dispatch region. This preserves source suspension and cleanup semantics despite C# prohibiting yield return in catch bodies and protected try bodies with catches.
The compiler catalogue compiles and executes this application for normal, rejected, alternating, empty, blank, whitespace, trailing-newline, absent and maximum-Decimal inputs. Separate actual-source tests cover sync/async handler suspension, original exception identity and stack frames, rethrow after reassignment, loop transfers, cancellation, early disposal and awaited cleanup before postconditions. These exercise the existing exception and iterator rules.
ReadStrictLimits uses a while loop inside try and stops at the first invalid amount. Its ordinary .NET ArgumentException records the one-based line number and retains the parsing/range exception as InnerException. It accepts zero and every nonnegative Decimal, using invariant parsing just like the row-classification path. Its reader remains owned by the iterator and closes on completion, failure or early consumer exit.
RejectStrict materializes the entire replacement with ToList before assigning it. A valid prefix can be yielded before an invalid line is reached; the iterator does not retract those rows or create a transaction. Finishing enumeration before replacing application data keeps the stored row unchanged when validation fails. Catalogue cases execute normal, empty, maximum, trailing-newline, malformed, overflowing, negative and absent strict inputs, alongside the original per-row handling cases.
ReadDelimitedLimits accepts semicolon-separated amounts using ordinary String.Split, Decimal.Parse and StringSplitOptions.None. Its for_each loop suspends inside try and reports the one-based position and original cause for malformed, overflowing or negative input. Empty text produces no rows; an empty field, including a trailing semicolon, is invalid. Whitespace follows invariant Decimal.Parse behavior.
String.Split explicitly creates the field array when enumeration first starts. Parsing remains incremental: a valid prefix can be observed before a later field fails, and stopping the consumer skips remaining parsing. This is distinct from the reader-based methods above, which do not split the entire input. The compiler captures the existing array once and adds no further buffering. DelimitedRun executes a valid batch; catalogue cases cover empty, whitespace, maximum, absent, malformed, negative, overflowing and trailing-field inputs.
Run the README example
import System
import System.Globalization
import System.IO
public class CustomerCreditImporter
static action ReadLimits(text as String)
yields CustomerCreditRow
require arguments.text is not nothing
let using reader = new StringReader(text)
let lineNumber = 0
let line = reader.ReadLine()
while line is not nothing
lineNumber += 1
try
let credit = Decimal.Parse(line, CultureInfo.InvariantCulture)
require credit >= 0 otherwise new ArgumentOutOfRangeException("creditLimit")
yield new CustomerCreditRow(lineNumber, credit, "")
catch FormatException
yield new CustomerCreditRow(lineNumber, nothing, "Credit limit must be a decimal number")
catch OverflowException
yield new CustomerCreditRow(lineNumber, nothing, "Credit limit exceeds the Decimal range")
catch ArgumentOutOfRangeException
yield new CustomerCreditRow(lineNumber, nothing, "Credit limit must not be negative")
end try
line = reader.ReadLine()
end while
end action
end class
import System
import System.Globalization
public class CreditImportExample
static action Run()
returns String
let input = "125.50" + Environment.NewLine + "invalid" + Environment.NewLine + "250"
let total as Decimal = 0
for_each row in CustomerCreditImporter.ReadLimits(input)
if row.CreditLimit is nothing then
Console.WriteLine("Line " + row.LineNumber + ": " + row.Error)
continue
end if
total += row.CreditLimit ?? 0
end for_each
let summary = "Accepted credit: " + total.ToString("F2", CultureInfo.InvariantCulture)
Console.WriteLine(summary)
return summary
end action
end class
This sample page preserves the complete ReadLimits action and CreditImportExample.ds, previously featured in the repository README. The returned CustomerCreditRow is an ordinary readonly result class. The compiler test compiles the exact published blocks together with that model, verifies their correspondence to these files and checks the printed output.
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry CreditImportExample.Run
It prints:
Line 2: Credit limit must be a decimal number
Accepted credit: 375.50
Nested row handling and a terminal credit failure
ReadUntilInvalidLimit accepts semicolon-delimited text. Inner grouped FormatException/OverflowException handlers emit a rejected row and continue. A negative parsed credit escapes the inner handlers, reaches the enclosing ArgumentOutOfRangeException handler, emits one rejected row and stops before later inputs. Empty text produces no rows; absent text fails its contract when enumeration begins. This policy preserves already published rows and adds no transactional rollback. The existing strict import remains a separate policy.
Run dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditImport/*.ds --entry Program.GuardedRun from the repository root. It prints Guarded credit import: 1:125.50;2:rejected;3:rejected; for 125.50;invalid;-1;250: the final 250 is not processed. Compiler cases execute that actual source for valid/zero/empty input, empty fields, malformed/overflow text, negative-first termination and an absent argument.
CustomerCreditPolicy
Source: Customer credit policy
A retail policy inherits a named base policy, derives its preferred credit limit
from an earlier readonly member, and makes an ordinary credit decision with a
native contract. All policy and decision logic is compiled from Program.ds.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditPolicy/Program.ds --entry CustomerCredit.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerCreditPolicy/Program.ds -o /tmp/CustomerCreditPolicy.cs
Output:
Approved
Manual review
StandardLimit, PreferredLimit and MaximumExposure initialize in source
order before the base constructor executes. The compiler currently supports
these derived-instance reads when the earlier readonly storage has a proven CLR
constant value. It preserves ordinary property/field types, access and readonly
metadata; reading the storage does not grant constant-only implicit conversions.
Runtime-dependent derived reads still require further pre-base lowering.
Compiler conformance cases and SDK integration tests compile this exact source, check both decisions and the negative-credit failure, and execute under both project overflow settings. Separate compiler cases observe initializer failure before base effects and once-only initialization through constructor delegation.
Configured runtime policy
RuntimePolicy.ds parses a base limit using ordinary .NET Decimal.Parse, then
calculates a preferred limit and its display text through earlier readonly
members. These initializers run once, in source order, before the base constructor;
they do not become post-base body assignments. The compiler uses private typed
bookkeeping and keeps the normal CLR fields/get-only properties.
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerCreditPolicy/RuntimePolicy.ds --entry CustomerCredit.RuntimePolicyExample.Run
Output:
Customer credit: 1200.00
The arithmetic, initialization dependencies and contract are DirectSharp source. A production configuration provider and the 20% policy remain application choices. Failure in any initializer still prevents a usable object and propagates the original exception. Mutable/custom initializer dependencies remain unsupported.
CustomerDeliverySchedule
Source: Customer delivery schedule
An ordinary Customer preference object parses a requested delivery day through
System.Enum.Parse, computes weekend and primary-customer flags, and stores
readonly properties. Invalid or absent text selects the application's Monday
fallback. The application logic is compiled from Program.ds.
From the repository root with the bootstrap .NET SDK:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/CustomerDeliverySchedule/Program.ds
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerDeliverySchedule/Program.ds --entry CustomerDelivery.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerDeliverySchedule/Program.ds -o CustomerDelivery.g.cs
Output:
Saturday:True:True
Monday:False:False
The native parse can fail before readonly state is stored. Once it succeeds,
the built-in enum and reference comparisons cannot invoke user-defined
operators or Equals. Constructor flow preserves that distinction so the
error handling branch cannot be entered after a successful readonly store merely
because of those comparisons. A selected user-defined operator, conversion or
throwing getter still retains its failure path.
Customer has ordinary reference identity: two different customer objects
remain different even if their property values match. Enum.Parse retains
its ordinary .NET behavior, including numeric text; the sample introduces no
new enum conversion or validation rule. Compiler conformance and SDK tests run
the exact source, including invalid and absent input, under both project
overflow settings.
CustomerDrafts
Source: Customer and supplier drafts with generic actions
This executable application uses one DraftFactory.Create action to construct two ordinary draft classes. Its <of T> declaration combines the documented base-class, interface and public parameterless-constructor constraints. The factory checks import inputs, initializes the name, invokes the nominal interface contract and checks normal-exit postconditions. All application behavior is compiled from Program.ds.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerDrafts/Program.ds --entry CustomerDrafts.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerDrafts/Program.ds -o /tmp/CustomerDrafts.cs
Output:
Ada:12/Acme:13
The compiler preserves a real CLR generic method. Generated C# combines the restrictions into where T : ImportDraft, IImportDraft, new(), and the body uses ordinary new T(), property assignment and interface dispatch. It does not inspect matching member names at runtime or use dependency injection to complete construction. The explicit type arguments are necessary because T occurs only in the result.
Program.Invalid supplies source row zero and throws ArgumentException before construction. The conformance catalogue executes both entry points. Compiler tests separately reject missing interface relationships, invalid/inaccessible constructors, circular constraints and duplicate generic signatures.
Generic actions are implemented for ordinary instance/static methods, including the tested callback, async and iterator combinations. Generic virtual/interface mappings and effective defaults for open type parameters remain explicit compiler boundaries. See compiler status for details.
CustomerImportOptions
Source: Customer import options
Program.ds builds an ordinary options object with readonly batch
size, audit setting and profile name. The constructor parses and validates text
before assigning state. Malformed or overflowing text falls back to a batch of
100; zero and negative batches raise ArgumentOutOfRangeException instead.
A missing profile fails the native require contract.
Run from the repository root with the .NET 8 bootstrap SDK:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerImportOptions/Program.ds --entry CustomerImports.Program.Run
Expected output:
250:True:retail
100:True:retail
Parsing and contracts can throw before any readonly member is assigned. After the first store, typed copies and a scalar comparison cannot throw; the compiler therefore keeps the successful construction path separate from error handling. Each normal path initializes every readonly member once.
let parsed = Integer.Parse(...) uses ordinary type inference. The constructor
analysis retains that resolved Integer type when checking later copies and
comparisons, while preserving the parse call's original failure paths.
Compiler execution tests cover valid, large, malformed, overflowing and invalid batch sizes. SDK tests compile this same source alongside C#, inspect its readonly CLR properties and execute it with overflow checking both enabled and disabled.
See construction rules, overflow rules and compiler implementation status.
CustomerPricing
Source: Customer pricing with action overloads
This application compiles its pricing policy from Program.ds. A caller can pass a Decimal subtotal for the standard policy or a PriceRequest containing the customer's preference status. Both calls resolve to the same case-insensitive Calculate action group, distinguished by parameter type.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerPricing/Program.ds --entry CustomerPricing.Program.Run
Output:
100.00/90.00
PriceRequest rejects negative subtotals during construction. The subtotal overload also checks its input before delegating to the request overload. The request overload requires a present request and checks its nonnegative result on both the preferred and ordinary return paths. All pricing decisions, contracts and formatting calls are compiled from DirectSharp source; C# supplies the generated backend and ordinary .NET libraries.
The two declarations deliberately use Calculate and calculate to exercise case-insensitive identity. Generated C# uses one canonical method spelling with two typed signatures. A production team would normally choose one spelling consistently. The simple 10% rule illustrates overloads and contracts; financial rounding, persistence and broader pricing policy remain application decisions.
Credit allocation
CreditAllocation.ds divides a nonnegative Decimal credit across two base
accounts plus a parsed Byte number of extra accounts. Its parsed-state, account
count and per-account credit are readonly. Parsing, the credit contract, checked
division and invalid-text error handling are all DirectSharp.
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerPricing/CreditAllocation.ds --entry CustomerPricing.CreditAllocations.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerPricing/CreditAllocation.ds -o /tmp/CreditAllocation.cs
Output:
4 accounts; 2.5 credit each
Invalid credit allocation
The denominator extra + 2 has a positive integral range of 2–257 and widens
exactly to Decimal. The compiler proves division safe after the first readonly
store, preserving the original calculation and .NET Decimal precision. This
sample reports raw credit shares; currency rounding, remainder distribution,
account persistence and the two-base-account policy belong to the application.
The small expression repeats because the current analysis does not infer its
runtime value from the previously stored account count.
Source conformance and SDK tests run ordinary and maximum credit values, invalid text, negative-credit contract failure and extra-account parse overflow under both project policies. Native overflow, zero divisors, foreign effects and whole- quotient conversion failures remain covered separately by compiler source tests.
CustomerQuotes
Source: Customer quotes with overridable policies
The pricing rules, interface, runtime defaults and contracts are written in Program.ds. A loyalty policy overrides an ordinary class action and calls the base implementation to apply its guards and calculation. The same policy also implements IQuotePolicy through an ordinary member mapping.
From the repository root, with the .NET 8 bootstrap SDK installed:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerQuotes/Program.ds --entry CustomerQuotes.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerQuotes/Program.ds -o /tmp/CustomerQuotes.cs
Expected output:
Customer quotes: 100.00/85.00/90.00
Interface quote: 90.00
| Call | Defaults evaluated | Result |
|---|---|---|
ordinary.Quote(100) through a QuotePolicy view |
preferred = false, then Rate(false) = 0 |
100.00 |
loyalty.Quote(100) through a LoyaltyQuotePolicy view |
preferred = true, then MemberRate(true) = 0.15 |
85.00 |
Named call through QuotePolicy supplying preferred: true |
Only Rate(true) = 0.10 |
90.00 |
Named call through IQuotePolicy supplying preferred: true |
Only the interface's QuotePolicy.Rate(true) = 0.10 |
90.00 |
All four calls dispatch to the loyalty override. The selected class or interface declaration determines which omitted defaults are evaluated; virtual/interface dispatch selects the body. Each default sees earlier effective parameters. Supplied values bypass their default expressions. The override's fully supplied base call invokes the base body directly, where negative subtotals and invalid discounts fail the native contracts.
The compiler preserves the full public CLR class and interface signatures. C# consumers supply complete argument lists, and native implementations satisfy only the original abstract interface members; generated presence/default helpers are internal. Exported logical omission metadata for separately compiled source libraries remains compiler implementation work. See the compiler progress tracker.
Actual-source tests compile and execute the example, check both contract failures, and call source policies through ordinary C# virtual slots. The SDK integration suite builds it alongside C# with warnings treated as errors.
Cancellable quote requests
QuoteAsync uses a declared optional CancellationToken, checks for cancellation, and calls the same virtual pricing action. Program.Request is explicitly async, so its omitted token argument forwards the caller's current token. The quote calculation and cancellation handling are DirectSharp source; Task.FromResult supplies a completed framework operation without simulating background work.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerQuotes/Program.ds --entry CustomerQuotes.Program.RunAsync
Expected output:
Async quote: 90.00
Canceled quote rejected: True
RequestSuccess verifies the preferred-customer price. RequestCanceled passes a pre-cancelled token and catches OperationCanceledException after awaiting the request. Ordinary native require/ensure checks still protect the pricing action. There is no implicit thread-pool scheduling or automatic cancellation check: QuoteAsync explicitly calls Cancellation.ThrowIfCanceled. An explicitly supplied different token overrides forwarding; without a caller cancellation context, the declared default supplies an empty token.
CustomerRecordImport
Source: Customer record construction and error handling
The two .ds files compile an ordinary immutable CustomerRecord with Id, Name and Email properties. Its constructor owns a StringReader, reads three lines through normal .NET APIs and initializes each readonly property once. Typed catches turn native ID parse/overflow failures into an ArgumentException attributed to record, preserving the original exception as InnerException. The reader is disposed before the catch runs. A failed constructor returns no usable record; it does not roll back arbitrary earlier effects.
From the repository root, using the .NET 8 SDK:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRecordImport/*.ds --entry Program.Run
dotnet run --no-build --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRecordImport/*.ds --entry Program.RejectInvalidId
Expected output:
Imported customer 42: Ana <ana@example.com>
Rejected record: record
Run trims the name/email and constructs a valid record. RejectInvalidId catches the translated argument error and verifies its parameter name and original FormatException. The conformance catalogue additionally exercises overflowing/nonpositive IDs, missing fields and extra lines. This is a three-line import format, not CSV or a full email-validation policy.
The shell expands *.ds; otherwise list CustomerRecord.ds and Program.ds with their paths. To inspect the C# or emit a CLR library DLL:
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerRecordImport/*.ds -o /tmp/CustomerRecordImport.cs
dotnet run --project compiler/DirectSharp.Compiler -- build compiler/fixtures/samples/CustomerRecordImport/*.ds -o /tmp/CustomerRecordImport.dll
Choose suitable output paths on Windows. The test runner compiles these exact sources and checks their runtime results and failures. Constructor flow through foreign calls/conversions is conservative: possible throw points enter catch analysis before the consuming store. Ambiguous readonly writes receive CL3002 rather than assuming a foreign call cannot throw. Other constructor tests cover initialization in finally and early returns after cleanup. The sample uses the compiler's supported subset; no feature adapter or C# business-logic substitute is involved.
For customer registration, validation and ordinary collection storage, continue with the Customer application.
CustomerRoster
Source: Streaming Customer roster
This runnable application reads one customer name per line, trims each name and rejects blank names. Both its synchronous and asynchronous readers are written in DirectSharp. They own an ordinary .NET StringReader and yield names as they are read.
An ensure checks the expected row count when enumeration completes normally, after the reader is disposed. The count stays in an ordinary local declared after let using. A short or oversized roster fails with InvalidOperationException during enumeration. Body, requirement, cancellation and cleanup failures propagate without running a successful-completion postcondition.
From the repository root, with the .NET 8 SDK installed:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/CustomerRoster/*.ds
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRoster/*.ds --entry Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRoster/*.ds --entry Program.Preview
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRoster/*.ds --entry Program.RejectIncomplete
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerRoster/*.ds --entry Program.RunAsync
The entries print:
Customer roster: 3 customers; first: Ana
Preview: Ana
Rejected incomplete roster
Async customer roster: 3 customers
Preview deliberately stops after the first name. That disposes the suspended iterator and its reader without asserting a total for input it did not finish reading. A source-level return, by comparison, is a normal completion and checks the iterator's postconditions.
RejectIncomplete materializes the replacement roster with ordinary LINQ ToList before assigning it to application state. The postcondition fails, so the previously stored customer stays unchanged. Already yielded names cannot be retracted: when a consumer needs an all-or-nothing replacement, it must finish validation before replacing its data. The iterator does not provide a transaction or an implicit snapshot.
To inspect the generated C# and emit a CLR library:
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/CustomerRoster/*.ds -o /tmp/CustomerRoster.cs
dotnet run --project compiler/DirectSharp.Compiler -- build compiler/fixtures/samples/CustomerRoster/*.ds -o /tmp/CustomerRoster.dll
The compiler catalogue compiles and executes the four entries plus empty, trimmed, short, oversized, blank, absent and negative-count inputs. Separate actual-source iterator tests check early disposal, failure identity, cancellation, independent enumerators, deferred/repeated execution and awaited cleanup before postconditions. These implement the existing contract and iterator rules.
CustomerSelection
Source: Select an enabled customer
The business logic in Program.ds selects the first enabled customer
from an ordinary .NET sequence. Construction assigns a readonly Customer once,
then returns from the loop. An empty or entirely disabled sequence raises
KeyNotFoundException; a missing sequence fails the native require contract.
The selected object retains its original identity.
From the repository root with the .NET 8 bootstrap SDK:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/CustomerSelection/Program.ds --entry CustomerSelection.Program.Run
Expected output:
Selected customer: Ada
Customer.MinimumId is a named compile-time constant used by the constructor's
validation rule. It exports a normal CLR constant field.
The example also uses constructor-promoted properties, typed generic .NET
collections and ordinary framework exceptions. Returning from the constructor
still disposes the enumerator; a cleanup failure propagates rather than publishing
a successfully constructed selection. Compiler integration tests exercise this
behavior with native enumerators that record disposal and throw original
exceptions. The SDK project tests compile this same .ds source alongside C#.
See construction and readonly rules and compiler implementation status.
DeliveryPositions
Source: Mutable .NET values in DirectSharp
This small application stores a normal System.Drawing.Point in a private field of an ordinary DirectSharp class. Movement updates that field's actual storage through the Point's X/Y properties. Point is the cross-platform coordinate type from System.Drawing.Primitives.
ReadHorizontal parses one coordinate line through an owned StringReader before storing the result. Invalid, overflowing or extra-line input propagates its ordinary failure and leaves both coordinates unchanged. The position starts at (2,3), moves to (7,2), imports horizontal coordinate 11, then moves to (10,4).
From compiler/, with the .NET 8 SDK installed:
dotnet run --project DirectSharp.Compiler -- run ../compiler/fixtures/samples/DeliveryPositions/*.ds --entry Program.Run
dotnet run --project DirectSharp.Compiler -- run ../compiler/fixtures/samples/DeliveryPositions/*.ds --entry Program.MoveFromText
dotnet run --project DirectSharp.Compiler -- transpile ../compiler/fixtures/samples/DeliveryPositions/*.ds -o /tmp/DeliveryPositions.cs
dotnet run --project DirectSharp.Compiler -- build ../compiler/fixtures/samples/DeliveryPositions/*.ds -o /tmp/DeliveryPositions.dll
Expected output:
Delivery position: 10,4
The second entry prints Moved delivery position: 7,2. MoveFromText calls the ordinary mutating Point.Offset method with two resource-valued arguments. Each StringReader is cleaned up before the next argument or the Offset call. Invalid movement or extra-line input prevents Offset from running and leaves both coordinates unchanged.
The compiler catalogue compiles these two .ds files, executes both entries and checks their rejection paths. All application logic lives in DirectSharp source; the Point, StringReader and exception implementations are ordinary .NET APIs. Coordinates are integer grid positions and use the bootstrap's native Integer arithmetic.
ExternalValidation
Source: Calling an external .NET library
Program.ds calls the real FluentValidation 11.11.0 assembly through its ordinary public results API. It constructs ValidationFailure and ValidationResult, enumerates errors, reads properties and prints:
Email: Email is required
From compiler/, build the test project once to restore and copy the pinned library as fixture data, then run the DirectSharp source:
dotnet build DirectSharp.Compiler.Tests
dotnet run --no-build --project DirectSharp.Compiler -- run ../compiler/fixtures/samples/ExternalValidation/Program.ds --reference DirectSharp.Compiler.Tests/bin/Debug/net8.0/references/FluentValidation.dll --entry ExternalValidation.Run
The same --reference option works with check, transpile and build. It can point at any compatible managed assembly file. Repeat it for each external dependency; a namespace import alone does not supply an assembly. This explicit-DLL path does not restore packages or discover DLLs beside a referenced file.
Alternatively, use the included ordinary SDK dependency context. From compiler/, after building the compiler:
dotnet run --no-build --project DirectSharp.Compiler -- run ../compiler/fixtures/samples/ExternalValidation/Program.ds --project ../compiler/fixtures/samples/ExternalValidation/Dependencies.csproj --entry ExternalValidation.Run
Dependencies.csproj pins the same FluentValidation package without implementing application logic. The .NET SDK performs restore/build and selects compile/runtime dependency assets. Source files remain explicit, and DirectSharp still binds the real public library APIs. See the SDK context limits before using other project targets or deployment assets.
The printing action constructs its results explicitly. InheritedValidatorIsValid additionally constructs a DirectSharp subclass of the real AbstractValidator<ValidationCustomer> and invokes its inherited Validate method. The empty validator tests inheritance in isolation. CustomerRules also defines real RuleFor/NotEmpty/Length rules with DirectSharp expression-tree selectors; ValidationRulesApplication.Accept, Reject and DescribeFailures test their results. Absence-preserving selectors lower to block expressions, so the rules explicitly call the ordinary OverridePropertyName API to keep readable field names in errors. The complete executable Customer variant additionally exercises EmailAddress and ValidateAndThrow. The compiler has no FluentValidation-specific transformations.
The compiler tests deliberately restore FluentValidation as data rather than a project/host reference. Without --reference, these source files fail to bind. Tests compile, emit and execute both this program and its EmptyIsValid action; CLI subprocess tests also exercise real external-library loading. This is separate from native C# reference-fixture evidence.
GenericCustomerStore
Source: A typed store for customers and numbers
Program.ds compiles a normal generic Store class, a generic IReadStore interface, an ordinary Customer and the application entry point. Store owns a fresh List for each instance. Add and First retain T; ProjectFirst declares its own TResult and accepts an ordinary .NET Func callback. The application uses Store<Customer> and Store<Integer> without boxing the store's public payload contract.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/GenericCustomerStore/Program.ds --entry GenericCustomerStore.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- format compiler/fixtures/samples/GenericCustomerStore/Program.ds --check
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/GenericCustomerStore/Program.ds -o /tmp/GenericCustomerStore.cs
Output:
Ada/Ada/7
The class explicitly maps First to IReadStore<T>. The application reads through that interface, executes a projection callback and reads a separate Integer store. Customer rejects an empty name; First rejects an empty store with InvalidOperationException. Program.Empty is an automated failure case. This in-memory example has no persistence, tracking or concurrency policy.
Generated C# retains CLR Store<T>/IReadStore<T> identities, typed List<T> storage and a ProjectFirst<TResult> method. Application behavior is compiled from DirectSharp source. Open-type effective defaults and generic virtual/interface actions remain explicit compiler boundaries; this example initializes a known List<T> and uses an ordinary non-virtual generic action.
ImportBatchSummary
Source: Customer import batch summary
Program.ds parses a row count and reports the complete 100-row batches and
remaining rows. The summary properties are readonly. Invalid text initializes
a fallback, negative counts fail the authored contract, and parse overflow
retains the ordinary .NET exception.
All parsing, validation, arithmetic, error handling and summary logic is DirectSharp source. From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/ImportBatchSummary/Program.ds --entry CustomerImports.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/ImportBatchSummary/Program.ds -o /tmp/ImportBatchSummary.cs
Output:
2 complete batches; 50 rows remaining
Invalid row count
Parsing and validation precede every readonly store. The compiler proves that
integer division and remainder by the declared constant BatchSize = 100
cannot throw; it does not invent a second initialization path after those
calculations. The emitted C# retains the original operations and their types.
Compiler conformance and SDK tests compile this exact source, run both summary
paths, check Integer.MaxValue and verify the negative-count exception under
both project overflow settings. Other compiler cases retain signed-minimum,
zero-divisor, Decimal overflow and conversion failures. Unproven runtime divisors still
require conservative analysis; a local initialized to 100 does not receive the
same proof as a validated const.
Import distribution
Distribution.ds shares a nonnegative row count across two base workers plus a
parsed Byte number of extra workers. Its readonly results report rows per worker,
remaining rows and the next one-based round-robin worker. Two base workers are
an example application policy, not a language rule.
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/ImportBatchSummary/Distribution.ds --entry CustomerImports.DistributionProgram.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/ImportBatchSummary/Distribution.ds -o /tmp/ImportDistribution.cs
Output:
3 workers: 3 rows each; 1 extra; next worker 2
Invalid import distribution
The divisor expression extra + 2 has range 2–257, so integral div and mod
cannot fail after the first readonly store. The remainder bounds also make the
next-worker calculation safe. Calculations and their checking contexts remain
visible in generated C#; parsing, validation and error handling are all DirectSharp.
The expression repeats deliberately: the current analysis does not propagate
runtime values through a local or a previously stored member.
Conformance and SDK tests compile this exact source under both overflow policies. They check ordinary/maximum row counts, invalid text, negative-count contract failure and extra-worker parse overflow. Separate compiler cases keep native zero-divisor, signed-minimum and intermediate-overflow exceptions observable.
MixedCSharpProject
Source: C# and DirectSharp in one project
A C# console host constructs an ordinary C# Order record and calls Pricing.Describe, compiled from Pricing.ds. DirectSharp validates its input, applies a ten-percent discount, and calls the C# formatting helper. The SDK compiles both languages into the same application.
From the repository root with the pinned .NET 8 SDK:
dotnet build compiler/DirectSharp.Compiler
dotnet build compiler/DirectSharp.Build
dotnet build compiler/fixtures/samples/MixedCSharpProject/MixedCSharpProject.csproj
dotnet run --no-build --project compiler/fixtures/samples/MixedCSharpProject/MixedCSharpProject.csproj
Output:
Ada: 90.00
MixedCSharpProject.csproj imports the local build tools and marks Pricing.ds with Build Action DirectSharpCompile. Open this project in Visual Studio to use the same build integration. Inspect obj/Debug/net8.0/directsharp/DirectSharp.g.cs after building; it is generated and compiled automatically. Set Custom Tool to empty. See the project integration guide for setup, source selection, diagnostics and verification limits.
The calculation and native contracts are DirectSharp source. Host.cs supplies the entry point, input record and invariant formatter. Automated SDK build/execution tests live in DirectSharp.Build.Tests; a Linux SDK test does not establish interactive Windows Visual Studio support.
NamespacedCustomers
Source: Customers across namespaces
This application compiles its model and service from actual DirectSharp source. Project.ds sets CustomerPortal as the root namespace and shares ordinary .NET imports. The relative headers namespace Domain and namespace Services place the classes in CustomerPortal.Domain and CustomerPortal.Services. Program has no namespace header, so it belongs to CustomerPortal.
From the repository root with the .NET 8 SDK:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/NamespacedCustomers/*.ds
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/NamespacedCustomers/*.ds -o /tmp/NamespacedCustomers.cs
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/NamespacedCustomers/*.ds --entry CustomerPortal.Program.Run
The program prints 1: Ana Petrova. CustomerPortal.Program.Missing returns true; CustomerPortal.Program.Duplicate throws InvalidOperationException for a duplicate ID. The compiler conformance catalogue executes all three paths.
The model enforces constructor requirements and a rename postcondition. The service uses ordinary List and LINQ APIs, rejects duplicate IDs, and returns nothing when lookup finds no customer. Property reads keep the language's absence behavior.
Use namespace Global.Infrastructure to place a file outside the configured root. Global. also bypasses the root in imports and qualified type references. Namespace and type identity are case-insensitive; emitted C# retains canonical spelling. Each source file currently accepts one namespace header before its types.
OrderApproval
Source: Order approval
Order.ds and Program.ds implement an ordinary order-approval workflow in DirectSharp. The compiler catalogue executes the application and its boundary cases.
From the repository root, with the .NET 8 SDK installed:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/OrderApproval/*.ds
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/OrderApproval/*.ds --entry Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/OrderApproval/*.ds -o /tmp/OrderApproval.cs
dotnet run --project compiler/DirectSharp.Compiler -- build compiler/fixtures/samples/OrderApproval/*.ds -o /tmp/OrderApproval.dll
The program prints Ana Petrova: approved 100.
An order owns an ordinary .NET List of positive Decimal line amounts. Its customer name is trimmed once during construction. A zero or negative line amount fails before it can be stored. Empty orders and orders exceeding available credit are declined and remain editable. Exact-credit approval succeeds; approval closes the order to further edits and repeated approval. The postcondition checks that the approval result agrees with the stored state on each normal exit.
Checks.ds supplies actual-source boundary operations invoked by the compiler catalogue. They cover exact/insufficient/excess credit, empty orders, changes after a decline, invalid amounts/names/credit, editing an approved order and repeated approval. No order logic is supplied by C# test fixtures.
This is an application policy, not a payment processor: it has no tax, currency conversion, persistence, transaction or concurrency guarantee. Decimal overflow propagates rather than producing a partial total or marking an order approved. See the Customer application and credit importer for ordinary validation, storage boundaries and streamed input.
OrderLineTotals
Source: Order line totals
Program.ds parses a quantity and unit price in cents, calculates a readonly
order-line total, and recovers from invalid text. The quantity is a CLR Byte and
the price is UInt16; the largest product, 16,711,425, fits Integer. The authored
checked expression remains checked in generated C#.
Parsing and the positive-quantity contract run before any readonly store. The
compiler uses the declared primitive input ranges to prove that the subsequent
multiplication cannot throw. It preserves normal native parse overflow and the
contract's ArgumentOutOfRangeException; it does not clamp invalid quantities.
All business logic is compiled from DirectSharp source. From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/OrderLineTotals/Program.ds --entry Orders.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/OrderLineTotals/Program.ds -o /tmp/OrderLineTotals.cs
Output:
3750 cents
Invalid order line
Compiler conformance and SDK tests compile this exact source. They check ordinary and maximum inputs, invalid text, zero-quantity contract failure and native out-of-range parsing under both project overflow settings. Other compiler cases verify that potentially overflowing arithmetic and runtime locals without constant evidence retain conservative construction diagnostics. This sample is a bounded integer calculation, not a new monetary type or pricing-library API.
Shipment quote
ShipmentQuote.ds extends the calculation with a fixed 125-cent packing fee.
Its readonly total adds packing to the item subtotal; its signed item refund
excludes packing. These are example application policies. Parsing, contracts,
nested checked calculations and invalid-text error handling are all DirectSharp.
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/OrderLineTotals/ShipmentQuote.ds --entry Orders.ShipmentQuotes.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/OrderLineTotals/ShipmentQuote.ds -o /tmp/ShipmentQuote.cs
Output:
Total: 3875 cents; item refund: -3750 cents
Invalid shipment quote
The compiler retains the bounded product when adding packing or negating it. Checks stay enabled in the emitted C#. Source conformance and SDK tests cover ordinary/maximum inputs, invalid text, the quantity contract and parse overflow under both project settings. Separate compiler cases retain failing intermediate arithmetic, unsafe negation, unchecked wrapping and getter evaluation; multiplying a result by zero does not suppress earlier failures.
ProjectImports
Source: Project-wide imports in a Customer summary
Project.ds supplies shared .NET imports to the two application source files. CustomerSummary formats a sequence of customer names with an ordinary LINQ filter and StringBuilder; Program constructs the input and prints Ana, Boris. The business logic is compiled from actual .ds files.
From compiler/:
dotnet build DirectSharp.Compiler
dotnet run --no-build --project DirectSharp.Compiler -- run ../compiler/fixtures/samples/ProjectImports/*.ds --entry ProjectImportsExample.Run
dotnet run --no-build --project DirectSharp.Compiler -- transpile ../compiler/fixtures/samples/ProjectImports/*.ds -o /tmp/ProjectImports.cs
dotnet run --no-build --project DirectSharp.Compiler -- build ../compiler/fixtures/samples/ProjectImports/*.ds -o /tmp/ProjectImports.dll
List Project.ds, CustomerSummary.ds and Program.ds explicitly if your shell does not expand wildcards. All three are compilation inputs. The project declaration determines the configuration scope; its filename is a recommendation. Imports outside it stay local to their source file.
The terminal System.Text.* import exposes the known namespace tree, including System.Text itself. Wildcard expansion uses referenced metadata, and introduces no assembly/package installation or import precedence. Global qualification resolves ambiguity. The standard-library root import can be disabled with auto_import_directsharp false inside project; that setting leaves manual imports available.
The application ignores absent name elements, trims present names, preserves input order and returns an empty String for an empty sequence. An absent sequence fails its require contract. The conformance cases execute all three outcomes, including the ordinary ArgumentNullException for the missing names input.
This source-level declaration is distinct from the SDK dependency context, which supplies assembly/package references. The compiler currently implements shared imports and the automatic-root setting; authored namespaces, root_namespace, aliases and assembly attributes remain future compiler work. See the implemented subsets for current boundaries.
ReportLocations
Source: Report directory selection
This application selects a per-user report directory through ordinary .NET APIs. Environment.SpecialFolder and Environment.SpecialFolderOption are enums declared inside System.Environment. DirectSharp uses their normal CLR names, values and overloads; no adapter is needed.
The readonly ReportLocation.Folder property, constructor parameter, enum values and GetFolderPath call are compiled from the two .ds files. Destination checks that the operating system supplied a base directory, then combines its path with DirectSharp/Reports. It does not create directories or write files. DoNotVerify asks .NET for the configured location without requiring the directory to exist.
From the repository root, with .NET 8 installed:
dotnet run --project compiler/DirectSharp.Compiler -- check compiler/fixtures/samples/ReportLocations/*.ds
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/ReportLocations/*.ds --entry Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/ReportLocations/*.ds -o /tmp/ReportLocations.cs
dotnet run --project compiler/DirectSharp.Compiler -- build compiler/fixtures/samples/ReportLocations/*.ds -o /tmp/ReportLocations.dll
Program.Run prints the report directory and returns whether it is an absolute path. The exact path depends on the operating system and user profile; Linux typically uses $HOME/.local/share/DirectSharp/Reports. Program.Category returns LocalApplicationData independently of the directory's existence. An unavailable system folder fails the contract instead of silently selecting a relative path.
The compiler catalogue executes both entries. See Getting Started for the connected Customer application and .NET interoperability for the language rules.
ReportProgress
Source: Report progress
Program.ds parses elapsed seconds with ordinary .NET APIs, calculates complete
report periods and the remaining seconds, and falls back after invalid text.
Readonly properties are assigned once on each successful construction path.
The parsing, arithmetic, error handling and summary logic are all DirectSharp source.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- run compiler/fixtures/samples/ReportProgress/Program.ds --entry Reports.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile compiler/fixtures/samples/ReportProgress/Program.ds -o /tmp/ReportProgress.cs
Output:
2 complete periods; 5 seconds remaining
Invalid elapsed time
Parsing precedes every readonly store, so a parse failure can initialize the
fallback. Floating mod follows normal .NET remainder behavior. The explicit
unchecked around div applies to the quotient's conversion to Long; it does
not change parsing or catch errors. A nonpositive period fails the input contract.
Compiler conformance and SDK tests compile this exact file, execute both summary paths and the invalid-period contract, and run under both project overflow settings. Separate compiler cases verify IEEE edge cases and keep potentially throwing checked, Decimal, integral and foreign operations conservative.
StockReservation
Source: Stock reservation
Program.ds implements an ordinary stock reservation: validate the inputs, calculate a readonly balance in a checked block, then reject insufficient stock. Arithmetic overflow propagates as the standard .NET OverflowException. The rule works independently of the generated project's default overflow setting.
From the repository root:
dotnet run --project compiler/DirectSharp.Compiler -- check samples/StockReservation/Program.ds
dotnet run --project compiler/DirectSharp.Compiler -- run samples/StockReservation/Program.ds --entry Inventory.Program.Run
dotnet run --project compiler/DirectSharp.Compiler -- transpile samples/StockReservation/Program.ds -o StockReservation.g.cs
Output:
Remaining stock: 12
Rejected stock count overflow.
The checked block is a normal lexical scope. It controls applicable arithmetic
and conversions; it does not catch errors, change external method bodies or undo
earlier work. The generated C# contains the corresponding checked block.
Compiler conformance and SDK tests compile and execute this exact .ds source.
ReserveFromText(text, received, requested) adds a text-import path. A
checked(using ... end using) expression owns the reader, parses the incoming
count and adds received stock before publishing the value. Overflow and parse
failures propagate after disposal. The following entry prints Imported stock: 12:
dotnet run --project compiler/DirectSharp.Compiler -- run samples/StockReservation/Program.ds --entry Inventory.Program.ImportPreview
WorkloadComparisons
Source: API, domain, data analysis and model comparisons
These actual DirectSharp sources accompany the C# API/domain comparison and Python data/AI comparison.
- PurchaseOrder is an aggregate with constructor/input guards and protected submission state.
- OrderApi returns ordinary ASP.NET Core IResult values from an injected read-only dictionary.
- TelemetryAnalytics groups a single-pass source into service counts, errors and mean latency. TelemetryRow.ds supplies its ordinary input/summary classes.
- LinearClassifier evaluates a binary logistic model exported by the Python training example. It copies and checks its parameters and validates feature shape/finiteness.
With the .NET 8 SDK and Python 3.12 available, run from the repository root:
python3 -m venv /tmp/directsharp-workload-env
/tmp/directsharp-workload-env/bin/python -m pip install -r verification/comparisons/requirements-workloads.txt
/tmp/directsharp-workload-env/bin/python verification/comparisons/workloads.py
Supply --dotnet /path/to/dotnet when the SDK executable is not on PATH. On Windows, use your virtual environment's Scripts/python.exe instead of the POSIX path shown. The runner uses the repository SDK pin.
The runner extracts and compiles the exact published DirectSharp/C# fences, verifies their correspondence to these source files and executes assertion-only native hosts. ASP.NET Core references come from the installed .NET 8 shared framework. No framework adapter or package-specific compiler transformation is involved. Generated sources/projects/model artifacts live in a temporary directory.
HTTP checks execute IResult against actual native HttpContext objects and inspect status/JSON; they do not start a network server. Domain cases cover invalid IDs/amounts, an empty submission, repeated submission, editing after submission and Decimal overflow without mutation. Analytics cases compare DirectSharp, pandas and a SQLite query over valid data, check one-pass DirectSharp traversal and reject invalid DirectSharp/Python input. The SQL query assumes prevalidated table data.
The Python training fence actually fits scikit-learn LogisticRegression and exports its weights/intercept, feature order and positive-label contract. Both published scorers and the C# companion are checked against predict_proba on separate probe inputs at absolute tolerance 1e-12. Additional checks cover copied weights, invalid shape, nonfinite values, overflowing scores and stable extreme logits. Synthetic data supplies reproducible execution evidence, not a model-quality result or a general sklearn/ONNX converter.
This comparison evidence is separate from the compiler conformance catalogue and native-only reference fixtures. It establishes these workloads on the .NET 8 bootstrap, not full language, other framework versions, production hosting or performance parity.
Customer HTTP host startup
The language walkthrough presents CustomersController in DirectSharp. The following native ASP.NET Core startup example registers its ordinary CLR application contracts. Configuration and host startup are kept here alongside other operational integration details.
using System.Data.Common;
using Microsoft.Data.SqlClient;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("Customers")
?? throw new InvalidOperationException("Customers connection string is missing");
builder.Services.AddSingleton<Func<DbConnection>>(
() => new SqlConnection(connectionString));
builder.Services.AddSingleton<CustomerValidator>();
builder.Services.AddScoped<CustomerRepository>();
builder.Services.AddScoped<CustomerRegistrationService>();
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
Background export native hosting reference
The producer and consumer in the language example are DirectSharp. This native host reference supplies linked cancellation, bounded channel coordination and settlement using ordinary .NET APIs. Its callback-failure queue is an explicit application diagnostic policy.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
public static class DocumentExportHost
{
public static async Task RunAsync(
string connectionString,
string directory,
CancellationToken stoppingToken,
ConcurrentQueue<Exception> cancellationRequestFailures)
{
ArgumentNullException.ThrowIfNull(cancellationRequestFailures);
using var stop = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(stop.Token);
using var command = connection.CreateCommand();
command.CommandText = "SELECT Id, Body FROM dbo.Documents ORDER BY Id";
var jobs = Channel.CreateBounded<ExportJob>(new BoundedChannelOptions(32)
{
FullMode = BoundedChannelFullMode.Wait,
SingleWriter = true,
SingleReader = true
});
var producer = new DocumentExportProducer();
var worker = new DocumentExportWorker();
void RequestStop()
{
try { stop.Cancel(); }
catch (AggregateException callbackFailures)
{
cancellationRequestFailures.Enqueue(callbackFailures);
}
}
async Task ProduceAsync()
{
try
{
await producer.LoadAsync(command, jobs.Writer, stop.Token);
jobs.Writer.TryComplete();
}
catch (Exception failure)
{
jobs.Writer.TryComplete(failure);
RequestStop();
throw;
}
}
async Task ConsumeAsync()
{
try { await worker.RunAsync(jobs.Reader, directory, stop.Token); }
catch { RequestStop(); throw; }
}
await Task.WhenAll(ProduceAsync(), ConsumeAsync());
}
}