Buoy Language Reference

Developer Edition

Norman Palardy

2026

The Buoy Language Reference

Version: Draft 0.1

Chapter 1. Introduction

1.1 Design Principles

The design of Buoy is guided by the following principles.

Readability

Source code is written more often than it is read. Buoy therefore favors clarity and consistency over syntactic brevity.

Simplicity

A language feature should justify its existence. Features that duplicate existing capabilities or introduce unnecessary complexity are avoided.

Strong Static Typing

The compiler should detect programming errors whenever possible before program execution. Type information is used to verify program correctness while remaining unobtrusive through judicious use of type inference.

Explicit Intent

Program structure should communicate programmer intent. Distinct language constructs are used to represent distinct concepts. For example, a Function computes and returns a value, while a Sub performs an action without producing a result.

Orthogonality

Language features should compose naturally. A feature that applies to one category of declaration should, where practical, apply consistently to others. Generic programming is an example of this principle.

Practicality

Buoy is intended for writing real applications. The language favors solutions that are straightforward to understand, implement, and maintain over solutions that are theoretically elegant but difficult to use.

1.2 Scope

This document specifies the Buoy programming language.

It defines:

This document does not define implementation-specific behaviour unless explicitly stated.

1.3 A First Program

The traditional first program displays the text “Hello, World!” on the standard output stream.

print("Hello, World!")

The precise entry point and program structure depend upon the execution model described in Chapter 3.

1.4 Source Files

A Buoy program consists of one or more source files.

A source file contains declarations, executable statements, or both, depending upon the context in which the file is compiled.

The organization of source files into modules, packages, or compilation units is described in a later chapter.

1.5 Case Sensitivity

Unless explicitly stated otherwise, identifiers are case-sensitive.

The identifiers

Value
value
VALUE

represent three distinct identifiers.

The spelling of language keywords is fixed.

1.6 Language Evolution

The Buoy language is expected to evolve over time.

New language features may be introduced in future language revisions while preserving source compatibility whenever practical.

When compatibility cannot be preserved, the language specification shall identify the behavioural changes introduced by the newer revision.

1.7 Normative Language

Throughout this reference the following terminology is used consistently.

shall

indicates a mandatory language rule.

shall not

indicates prohibited behaviour.

should

indicates a recommendation.

may

indicates implementation-defined or optional behaviour.

Examples are informative and are not themselves part of the language specification.

1.8 Document Organization

The remainder of this reference is organized as follows.

Appendices provide the complete grammar, keyword list, operator precedence table, and other reference material.

Chapter 2. Lexical Structure

2.1 General

A Buoy program consists of one or more source files containing Unicode text.

During compilation, each source file is transformed into a sequence of lexical elements known as tokens. Tokens are the smallest meaningful elements of the language and include identifiers, keywords, literals, operators, punctuation, and comments.

Except where explicitly stated, whitespace and comments serve only to separate tokens and have no semantic meaning.


2.2 Character Set

Buoy source files are encoded as Unicode text.

The compiler shall recognize the Unicode characters required to represent identifiers, string literals, comments, and source code punctuation.

Implementations should accept UTF-8 encoded source files.


2.3 Source Lines

A source file is composed of a sequence of source lines.

A source line may contain:

The significance of line endings is determined by the grammar of the enclosing construct.


2.4 Whitespace

Whitespace separates adjacent lexical elements.

Whitespace may appear between any two tokens unless prohibited by the grammar.

The following characters are considered whitespace:

Multiple whitespace characters are equivalent to a single separator unless they occur within a string literal.


2.5 Comments

Comments are ignored by the compiler except where required for documentation generation.

Comments may appear wherever whitespace is permitted.

The syntax of comments is described in Section 2.11.


2.6 Identifiers

Identifiers name language entities including variables, constants, functions, subroutines, types, modules, properties, parameters, and classes.

An identifier consists of a sequence of characters beginning with a valid identifier-start character followed by zero or more identifier characters.

Unless otherwise specified, identifiers are case-sensitive.

The following identifiers are distinct:

Value
value
VALUE

Identifiers shall not be identical to reserved words.

The complete list of reserved words is provided in Appendix A.


2.7 Keywords

Keywords are reserved identifiers having predefined meaning within the language.

Examples include:

If
Then
Else
For
While
Function
Sub
Class
Structure
Interface
Module
Return
Const
Var
Dim

Keywords shall be used only according to the grammar of the language.


2.8 Literals

A literal denotes a constant value written directly in source code.

Buoy defines literal forms for:

The syntax and semantics of each literal form are described in later chapters.


2.9 Operators and Punctuation

Operators perform computations upon one or more operands.

Examples include arithmetic, comparison, logical, assignment, and member-access operators.

Punctuation characters delimit grammatical constructs such as parameter lists, array indexing expressions, generic type arguments, and statement blocks.

Operator precedence and associativity are defined in Appendix B.


2.10 Case Sensitivity

Keyword spelling is fixed.

Identifier comparison is case-sensitive.

String comparison semantics are determined by the operations performing the comparison and are independent of identifier matching.


2.11 Documentation Comments

Buoy supports documentation comments for generating API documentation.

Documentation comments are associated with the declaration immediately following the comment.

The syntax and processing rules for documentation comments are described in Chapter 27.


2.12 Lexical Errors

A lexical error occurs when the compiler encounters source text that cannot be tokenized.

Examples include:

A conforming compiler shall report the location of the offending source text before terminating compilation.


2.13 Summary

The lexical structure defined by this chapter establishes the sequence of tokens consumed by the parser.

Subsequent chapters describe how those tokens combine to form declarations, expressions, statements, and complete programs.

Chapter 3. Program Structure

3.1 General

A Buoy program consists of one or more source files compiled as a single program or library.

A source file contains declarations that define the program’s types, variables, constants, callable routines, and other program elements. Depending upon the declaration, executable statements may also appear within the source file.

The organization of declarations determines the visibility and lifetime of the entities they introduce.


3.2 Compilation Units

A compilation unit is the basic unit of source code accepted by the compiler.

Each source file forms a compilation unit.

During compilation, all compilation units participating in a build are parsed, analysed, and combined according to the language’s name-resolution rules.

The order in which source files are presented to the compiler shall not affect the meaning of a valid program.


3.3 Program Organization

Programs are organized through declarations.

Typical declarations include:

Each declaration introduces one or more names into a scope.

The precise syntax of each declaration is defined in the corresponding chapter.


3.4 Scope

A scope is the region of source code within which a declared name is visible.

Every declaration introduces its name into exactly one scope.

Nested declarations create nested scopes.

When multiple declarations use the same identifier, the declaration in the innermost enclosing scope is selected.

Rules governing shadowing and name hiding are described in Chapter 5.


3.5 Declarations

A declaration introduces a program entity.

Depending upon the declaration kind, it may specify:

Some declarations introduce executable code.

Others exist solely to define program structure.


3.6 Executable Statements

Executable statements describe actions performed when a program runs.

Statements may:

Statements appear only where permitted by the grammar.


3.7 Blocks

A block is a sequence of declarations and statements treated as a single grammatical unit.

Blocks establish nested scopes.

Variables declared within a block cease to exist when execution leaves that block.

Control-flow constructs such as conditional statements and loops typically introduce blocks.


3.8 Name Resolution

Whenever an identifier appears within a program, the compiler attempts to resolve that identifier to a declaration.

Name resolution considers:

If more than one declaration is applicable, overload resolution or ambiguity rules are applied as appropriate.

Failure to resolve an identifier results in a compile-time error.


3.9 Program Entry

Executable programs begin execution at the language-defined entry point.

The exact form of the entry point and its permitted signatures are specified in Chapter 22.

Library projects are not required to define an entry point.


3.10 Separate Compilation

Implementations may compile source files independently.

Regardless of compilation strategy, a conforming implementation shall produce the same observable behaviour as if the entire program had been analysed as a single translation.


3.11 Attributes

Declarations may be annotated with attributes that provide additional information to the compiler or to external tools.

Attributes do not alter the syntax of the language.

The semantics of individual attributes are implementation-defined unless otherwise specified.


3.12 Conditional Compilation

Buoy supports conditional compilation to enable source code to be included or excluded according to compile-time conditions.

Conditional compilation directives are processed before syntactic analysis.

The syntax and semantics of these directives are described in Chapter 25.


3.13 Summary

The structure of a Buoy program is determined entirely by its declarations.

Subsequent chapters define each declaration kind and the rules governing its visibility, lifetime, and behaviour.

Chapter 4. The Type System

4.1 General

Every value in Buoy has a type.

A type defines the set of values that may be represented together with the operations that may be performed upon those values. The compiler uses type information to verify program correctness, resolve overloaded routines, infer the types of expressions, and generate efficient executable code.

Buoy is a statically typed language. Except where explicitly permitted by the language, the type of every expression is determined during compilation.


4.2 Static Typing

Type checking is performed at compile time.

A program that attempts an operation not defined for the operand types is ill-formed and shall be rejected by the compiler.

Examples of compile-time type errors include:

The compiler should diagnose type errors before code generation.


4.3 Type Categories

The Buoy type system consists of several categories of types.

These include:

Each category is described in a subsequent chapter.


4.4 Named Types

A named type is introduced by a type declaration.

Once declared, the type may be referenced wherever a type specification is permitted.

The scope and visibility of a type are determined by the declaration that introduces it.


4.5 Type Identity

Two types are identical if they denote the same declared type or if they are defined by the language to be equivalent.

Distinct declarations introduce distinct types, even when their internal representation is identical, unless otherwise specified by the language.

Type identity is used during assignment, parameter passing, overload resolution, and generic type substitution.


4.6 Type Compatibility

A value may be assigned to a destination only when the source type is compatible with the destination type.

Compatibility may arise through:

The precise compatibility rules are defined throughout this reference.


4.7 Type Inference

In certain contexts, the compiler may infer a type rather than requiring it to be written explicitly.

Type inference never changes the meaning of a program. It merely allows the compiler to determine a type that could otherwise have been written by the programmer.

Inference may occur for:

If more than one type satisfies the language rules, the compiler shall report an ambiguity.


4.8 Value Semantics and Reference Semantics

Some Buoy types exhibit value semantics.

Assignment of a value type copies the value.

Other types exhibit reference semantics.

Assignment of a reference type copies the reference rather than the referenced object.

The semantic category of each built-in and user-defined type is specified by its declaration.


4.9 Default Values

Every type has an associated default value.

When an object or variable is created without an explicit initializer, the implementation supplies the default value appropriate for its type.

The default value of each built-in type is described in the corresponding chapter.


4.10 Generic Types

Generic types define families of related types parameterized by one or more type parameters.

A generic declaration describes the structure and behaviour common to every specialization.

A constructed type is produced by substituting concrete type arguments for the generic parameters.

Generic types are discussed in detail in Chapter 18.


4.11 Type Conversions

A conversion transforms a value from one type to another.

Conversions may be:

An implicit conversion shall never lose information unless explicitly permitted by the language specification.

Conversions that may fail or lose information require explicit programmer intent.


4.12 Type Safety

The primary objective of the Buoy type system is to detect programming errors before execution.

A conforming implementation shall reject any program that violates the static type rules defined by this specification.

Programs accepted by the compiler may assume that every expression has a well-defined compile-time type.


4.13 Summary

The Buoy type system provides the foundation upon which declarations, expressions, and generic programming are built.

Subsequent chapters describe each category of type together with the operations supported by those types.

Chapter 5. Variables and Constants

5.1 General

Variables and constants associate names with values.

A variable denotes a storage location whose value may change during program execution.

A constant denotes a value that, once established, cannot subsequently be modified.

Both variables and constants are introduced by declarations.


5.2 Variable Declarations

A variable declaration introduces one or more variables into the current scope.

A declaration specifies:

The variable becomes visible immediately after its declaration, subject to the scope rules described in Chapter 3.


5.3 Variable Lifetime

The lifetime of a variable is determined by the declaration that introduces it.

Local variables are created when execution enters their enclosing scope and cease to exist when execution leaves that scope.

Member variables exist for the lifetime of the object or type to which they belong.

Static storage duration, if supported, is described in the chapter covering declarations.


5.4 Initialization

A variable may be initialized as part of its declaration.

When an initializer is present, the initializer expression is evaluated before the variable becomes available for subsequent use.

When no initializer is supplied, the compiler provides the default value for the variable’s type, unless the language requires definite assignment before use.


5.5 Type Inference

Where permitted, the compiler may infer the type of a variable from its initializer.

For example, if an initializer produces a value of type Integer, the declared variable acquires that type without requiring it to be written explicitly.

Type inference affects only the declaration syntax.

The inferred type is fixed once compilation succeeds.


5.6 Assignment

Assignment replaces the current value stored by a variable.

The value being assigned shall be compatible with the variable’s declared type.

Assignment does not alter the variable’s type.

Where a conversion is required, the conversion rules defined in Chapter 4 apply.


5.7 Definite Assignment

A variable shall not be read before a value has been assigned to it.

The compiler performs flow analysis to determine whether every execution path initializes the variable before its first use.

Failure to satisfy the definite assignment rules results in a compile-time error.


5.8 Constants

A constant declaration introduces a named value that cannot be modified after its initialization.

Every constant shall be initialized exactly once.

The initializer shall satisfy the restrictions imposed by the language for constant expressions.

Attempting to assign a new value to a constant is a compile-time error.


5.9 Scope

Variables and constants obey the lexical scope rules defined in Chapter 3.

A declaration hides any declaration of the same name in an enclosing scope.

Programs should avoid unnecessary shadowing, as it reduces readability.


5.10 Capture

When a local variable is referenced by a nested function, delegate, or anonymous routine, the implementation may capture the variable rather than its current value.

The semantics of captured variables are described in the chapter covering delegates and closures.


5.11 Summary

Variables provide mutable storage during program execution.

Constants provide immutable named values.

Together they form the foundation upon which expressions, statements, and callable routines operate.

Chapter 6. Expressions

6.1 General

An expression specifies a computation that produces a value.

Expressions are formed from literals, variables, constants, function invocations, operators, and other expressions. Every expression has a compile-time type that determines the operations that may be performed upon the resulting value.

Unless otherwise specified, evaluation of an expression does not modify program state.


6.2 Expression Categories

Expressions include, but are not limited to:

Each expression category is defined in the sections that follow.


6.3 Literal Expressions

A literal expression denotes a constant value written directly within the source code.

Examples include:

The type of a literal is determined by its lexical form and the surrounding context.


6.4 Variable References

A variable reference evaluates to the current value stored in the referenced variable.

The variable shall be visible at the point of reference and shall satisfy the definite assignment rules defined in Chapter 5.


6.5 Constant References

A constant reference evaluates to the value associated with the constant declaration.

The value of a constant cannot change during program execution.


6.6 Function Invocation

Invoking a function evaluates each argument, transfers control to the function body, and produces the value returned by the function.

Every execution path through a function shall produce a value compatible with the declared return type.

A function invocation is itself an expression and may therefore appear wherever an expression is permitted.

Example:

total = CalculateTotal(price, quantity)

6.7 Sub Invocation

A Sub performs an action but does not produce a value.

Because a Sub has no result, a Sub invocation is a statement rather than an expression.

The following is valid:

WriteReport(customer)

The following is invalid:

total = WriteReport(customer)

Attempting to use a Sub where a value is required is a compile-time error.


6.8 Parenthesized Expressions

Parentheses may be used to control evaluation order or improve readability.

A parenthesized expression has the same type and value as the enclosed expression.


6.9 Unary Operators

A unary operator acts upon a single operand.

Examples include:

The operand type shall support the selected operator.


6.10 Binary Operators

A binary operator combines two operands to produce a result.

Categories of binary operators include:

Each operator specifies:


6.11 Assignment

An assignment expression replaces the value stored by a variable.

The right-hand expression is evaluated before the assignment occurs.

The resulting value shall be compatible with the destination type.


6.12 Member Access

Member access selects a member of a composite value.

Members may include:

The referenced member shall be visible and accessible.


6.13 Indexing

Indexing selects an element of an indexed value.

The index expression shall evaluate to a valid index type.

The semantics of indexing are determined by the indexed type.


6.14 Evaluation Order

Unless otherwise specified, operands are evaluated from left to right.

The language guarantees that each operand is evaluated exactly once.

Programs shall not depend upon any alternative evaluation order.


6.15 Compile-Time Evaluation

The compiler may evaluate expressions during compilation when every operand is known at compile time.

Compile-time evaluation shall not alter the observable behaviour of a valid program.


6.16 Summary

Expressions compute values.

Every expression has a well-defined compile-time type, and every operator defines the relationship between its operands and its result.

Chapter 7. Statements

7.1 General

A statement describes an action performed during program execution.

Statements control the flow of execution, modify program state, invoke routines, and introduce local declarations.

A Buoy program executes by evaluating statements in the order determined by the language’s control-flow rules.


7.2 Statement Categories

The language defines the following categories of statements:

Additional statement forms may be introduced by future revisions of the language.


7.3 Blocks

A block is a sequence of zero or more statements treated as a single syntactic unit.

Blocks establish a new lexical scope.

Names declared within a block are visible only within that block and any nested blocks unless otherwise specified.

Execution proceeds sequentially from the first statement of the block to the last unless altered by a control-flow statement.


7.4 Empty Statements

An empty statement performs no action.

An implementation may permit empty statements where the grammar requires a statement but no operation is desired.

Empty statements have no observable effect.


7.5 Assignment Statements

An assignment statement evaluates an expression and stores the resulting value into a variable, property, or other assignable storage location.

The destination shall be writable and the assigned value shall be compatible with the destination type.

The assignment completes only after the right-hand expression has been fully evaluated.


7.6 Sub Invocation Statements

Invoking a Sub performs an action.

Because a Sub does not return a value, its invocation forms a statement rather than an expression.

Examples include:

Execution resumes with the statement immediately following the invocation once the Sub completes.


7.7 Conditional Statements

Conditional statements execute one of several alternative statement sequences depending upon the value of a Boolean expression.

The language provides conditional constructs including:

Only one alternative is executed for each evaluation of the conditional construct.


7.8 Iteration Statements

Iteration statements repeatedly execute a statement or block.

The language provides several iteration constructs appropriate for different programming tasks.

Typical forms include:

Each iteration construct specifies the conditions under which execution begins, continues, and terminates.


7.9 Jump Statements

Jump statements alter the normal sequential flow of execution.

Examples include:

Each jump statement transfers control to a well-defined destination determined by the enclosing construct.

Jump statements shall not transfer control into a nested scope.


7.10 Return

A Return statement terminates execution of the current Function or Sub.

Within a Function, Return specifies the value produced by the invocation.

Within a Sub, Return transfers control to the caller without producing a value.

A Function shall not complete execution without returning a value compatible with its declared return type.


7.11 Statement Execution

Unless otherwise specified, statements execute in source order.

Each statement completes before execution begins for the following statement.

The language defines additional ordering guarantees for expressions and routine invocations where necessary.


7.12 Reachability

The compiler performs control-flow analysis to determine whether a statement is reachable.

Statements that cannot be executed are considered unreachable.

A conforming implementation may diagnose unreachable statements during compilation.


7.13 Summary

Statements describe the executable behaviour of a Buoy program.

Expressions compute values.

Statements use those values to perform work, direct control flow, and modify program state.

Chapter 8. Functions and Subs

8.1 General

Functions and Subs are the primary executable units of a Buoy program.

Both define reusable sequences of statements that may accept parameters. A Function computes and returns a value to its caller. A Sub performs an action and does not return a value.

Although Functions and Subs share much of their syntax and behaviour, they represent distinct language constructs and are treated separately throughout this specification.


8.2 Function Declarations

A Function declaration introduces a named routine that computes and returns a value.

A Function declaration specifies:

The return type forms part of the function declaration and determines the type of every invocation.


8.3 Sub Declarations

A Sub declaration introduces a named routine that performs an action.

A Sub declaration specifies:

Unlike a Function, a Sub has no return type.


8.4 Parameters

Parameters introduce named values that are supplied by the caller when a routine is invoked.

Each parameter has:

Parameters are local to the routine in which they are declared.


8.5 Invocation

A routine is invoked by specifying its name followed by an argument list.

Each argument is evaluated before control transfers to the invoked routine.

Arguments shall satisfy the parameter requirements established by the declaration.

If no applicable declaration exists, the invocation is ill-formed.


8.6 Return

A Function returns control and a value to its caller.

Every execution path through a Function shall produce a value compatible with the declared return type.

A Sub returns only control.

Execution of a Sub completes when:


8.7 Local Variables

Variables declared within a Function or Sub are local to that routine.

Local variables are created upon entry to the routine and destroyed when execution leaves the routine.

Each invocation receives an independent set of local variables.


8.8 Overloading

Multiple Functions or Subs may share the same name provided their parameter lists satisfy the language rules for overload resolution.

Overload resolution is performed entirely at compile time.

The compiler selects the most appropriate declaration according to the argument types supplied by the invocation.

The overload resolution algorithm is described in Chapter 9.


8.9 Generic Routines

A Function or Sub may declare one or more generic type parameters.

Generic routines describe families of related routines whose behaviour depends upon the supplied type arguments.

Type arguments may be written explicitly or inferred by the compiler when permitted by the language.

Generic programming is described in Chapter 10.


8.10 Recursion

A Function or Sub may invoke itself either directly or indirectly.

Each recursive invocation creates a new execution context with its own parameters and local variables.

The language imposes no restriction upon recursive declarations beyond those required by available execution resources.


8.11 Visibility

The visibility of a Function or Sub is determined by its declaration.

A routine may be visible only within its declaring scope or may be exported for use by other compilation units, according to the applicable accessibility rules.


8.12 Forward References

A Function or Sub may invoke another routine declared elsewhere within the same program.

The compiler resolves routine references during semantic analysis.

The order of routine declarations within source files does not affect program correctness.


8.13 Routine Identity

A Function and a Sub are distinct declaration kinds.

A Function cannot be substituted for a Sub.

Likewise, a Sub cannot be used where a Function is required to produce a value.

This distinction is enforced during compilation.


8.14 Summary

Functions compute values.

Subs perform actions.

Together they provide the primary abstraction mechanism for executable behaviour in the Buoy programming language.

Chapter 9. Overload Resolution

9.1 General

Buoy permits multiple Functions and Subs to share the same name, provided that each declaration is distinguishable by its parameter list.

When a routine is invoked, the compiler determines which declaration is intended by applying the overload resolution rules defined in this chapter.

Overload resolution is performed entirely at compile time.


9.2 Candidate Set

Given a routine invocation, the compiler first constructs the candidate set.

The candidate set consists of every visible Function or Sub having the specified name and which is eligible for invocation in the current context.

Declarations that are inaccessible or otherwise unavailable are excluded.


9.3 Applicability

A candidate is applicable if each supplied argument can be matched with a corresponding parameter.

The compiler considers:

Candidates that fail to satisfy these requirements are discarded.


9.4 Best Match

If more than one applicable candidate remains, the compiler determines which candidate most closely matches the supplied arguments.

Preference is given to candidates requiring fewer or less significant conversions.

If a single best candidate exists, that declaration is selected.


9.5 Ambiguity

If more than one applicable candidate is equally suitable, the invocation is ambiguous.

An ambiguous invocation is a compile-time error.

The programmer may resolve the ambiguity by:


9.6 Generic Routines

Generic Functions and Subs participate in overload resolution.

Before comparing candidates, the compiler attempts to infer generic type arguments from the supplied arguments.

A candidate for which type inference fails is not considered applicable.

If more than one generic specialization is applicable, the normal overload resolution rules apply.


9.7 Functions and Subs

Functions and Subs occupy distinct semantic roles.

A Function invocation is valid only where a value is required.

A Sub invocation is valid only as a statement.

Accordingly, overload resolution never substitutes a Sub for a Function, nor a Function for a Sub.


9.8 Accessibility

Only declarations visible at the invocation point participate in overload resolution.

Hidden or inaccessible declarations are ignored.


9.9 Compile-Time Determination

Routine selection is completed before program execution.

The selected declaration remains fixed for that invocation.

Runtime behaviour does not influence overload selection except where explicitly specified by later language features.


9.10 Summary

Overload resolution enables related routines to share a common name while preserving compile-time type safety.

The compiler selects a single declaration using the argument list, parameter types, type inference, and the rules defined in this chapter.

Chapter 10. Generic Programming

10.1 General

Generic programming enables algorithms and data types to operate upon values whose types are specified when the generic entity is used rather than when it is declared.

A single generic declaration therefore describes a family of related declarations.

Generic programming promotes type safety, code reuse, and compile-time verification without sacrificing performance.

Generic facilities are integrated throughout the Buoy language and are not limited to a particular category of declaration.


10.2 Generic Declarations

A declaration is generic when it introduces one or more type parameters.

Type parameters represent placeholder types whose concrete values are supplied or inferred when the declaration is used.

The language permits generic:

Additional declaration kinds may support generic parameters where explicitly specified.


10.3 Type Parameters

Each type parameter introduces a symbolic name representing an unknown type.

Within the generic declaration, the type parameter may appear wherever a type specification is permitted.

Each distinct type parameter represents an independent type.

Type parameter names obey the normal rules governing identifier visibility and scope.


10.4 Constructed Types

A constructed declaration is produced by substituting concrete type arguments for every type parameter.

Each unique set of type arguments identifies a distinct specialization.

The compiler shall ensure that every substituted type satisfies the requirements imposed by the generic declaration.


10.5 Generic Functions and Subs

Generic routines behave exactly like ordinary routines except that one or more types remain unspecified until invocation.

Generic routines participate fully in overload resolution.

Type arguments may be supplied explicitly or inferred by the compiler.


10.6 Type Inference

Where sufficient information is available, the compiler shall infer generic type arguments automatically.

Type inference considers:

The inferred types shall produce the same semantics as if they had been written explicitly.

Failure to infer a unique type is a compile-time error.


10.7 Explicit Type Arguments

A programmer may explicitly specify generic type arguments.

Explicit type arguments override inference.

Every supplied type argument shall satisfy the requirements of the corresponding type parameter.


10.8 Generic Members

Members declared within a generic type may reference the enclosing type parameters.

A member may also declare additional generic parameters independent of those declared by the enclosing type.

The scopes of enclosing and local type parameters are distinct.


10.9 Nested Generic Declarations

A generic declaration may contain additional generic declarations.

Inner declarations may reference both their own type parameters and those declared by enclosing declarations, subject to the normal visibility rules.


10.10 Type Safety

Generic programming preserves the static type guarantees of the language.

Every specialization is type checked according to the same language rules as a non-generic declaration.

No operation permitted within a generic declaration may violate the type safety of a valid specialization.


10.11 Code Generation

The language specification defines only the observable behaviour of generic declarations.

A conforming implementation may generate specialized code, shared code, or any other equivalent representation provided the externally observable behaviour remains unchanged.


10.12 Summary

Generic programming allows algorithms and data structures to be expressed independently of the concrete types upon which they operate.

Generic declarations are fully integrated with the Buoy type system, overload resolution, and compile-time type inference.

Chapter 11. Classes

11.1 General

A class defines a user-defined reference type that combines data and executable behaviour into a single declaration.

A class may declare:

A class declaration introduces a new named type.


11.2 Class Declarations

A class declaration specifies:

The class body contains the declarations that define the state and behaviour of instances of the class.


11.3 Instances

An instance is an object created from a class.

Each instance contains its own copy of the instance state declared by the class.

Member Functions and Subs operate upon a particular instance unless declared otherwise.

The mechanism used to create instances is described in Section 11.7.


11.4 Members

Members define the capabilities of a class.

A class may contain:

Each member has its own accessibility, lifetime, and semantics.

The grammar for each member category is described in the corresponding chapter.


11.5 Visibility

Member visibility determines where a member may be referenced.

The language defines accessibility rules that govern the visibility of declarations both within and outside the declaring class.

Accessibility is enforced during compilation.


11.6 Member Invocation

Member Functions and Subs are invoked through an instance of the class unless declared as type members.

Invocation follows the same overload resolution and parameter matching rules defined for all routines.

The only distinction is that the invocation occurs within the context of a particular object.


11.7 Construction

An object is created by invoking one of the constructors defined by the class.

Construction allocates storage for the new instance and performs any initialization required by the class.

If multiple constructors are declared, overload resolution determines which constructor is invoked.

The construction process completes before the resulting object becomes available to the caller.


11.8 Object Lifetime

The lifetime of an object begins when construction completes.

The mechanism by which object storage is reclaimed is implementation-defined.

Programs shall not depend upon any particular memory management strategy unless explicitly documented by the implementation.


11.9 Generic Classes

A class may declare one or more generic type parameters.

Each specialization of a generic class represents a distinct constructed type.

Generic classes participate fully in the generic programming facilities described in Chapter 10.


11.10 Nested Classes

A class may contain additional class declarations.

Nested classes obey the normal rules governing visibility, accessibility, and generic parameter scope.


11.11 Summary

Classes define reference types that combine state and behaviour.

They provide the primary mechanism for representing complex program entities whose lifetime extends beyond a single routine invocation.

Chapter 12. Structures

12.1 General

A Structure defines a user-defined value type.

A Structure groups related values into a single composite type while retaining value semantics. Assignment of a Structure copies the value represented by the Structure rather than creating an additional reference to the same object.

Structures are appropriate for representing values that possess identity only through their contents.

12.2 Structure Declarations

A Structure declaration introduces a new named value type.

A Structure may declare fields, properties, constants, Functions, Subs, constructors, nested declarations, and generic parameters.

12.3 Value Semantics

Variables of Structure type contain the Structure value directly. Assigning one Structure variable to another copies the complete value. Subsequent modification of either variable does not affect the other.

Example:

Structure Point
X As Integer
Y As Integer
End Structure

Dim p1 As Point
Dim p2 = p1

After the assignment, p1 and p2 represent independent values.

12.4 Members

A Structure member behaves according to the same language rules governing members of a Class unless otherwise specified.

12.5 Construction

A Structure instance is created according to the construction rules defined for Structure types.

12.6 Passing Structures

When a Structure is supplied as an argument, the parameter passing mechanism determines whether the value is copied or whether the called routine operates directly upon the supplied value.

12.7 Generic Structures

Structures may declare generic parameters.

12.8 Summary

Structures provide efficient composite value types while preserving the static type guarantees of the language.

Chapter 13. Interfaces

13.1 General

An Interface specifies a contract.

Rather than describing how an operation is performed, an Interface specifies which operations shall be provided by any type implementing the Interface.

13.2 Interface Declarations

An Interface may declare Functions, Subs, properties, constants and nested declarations.

13.3 Implementation

A Class or Structure may implement one or more Interfaces.

A type implementing an Interface shall provide every required member defined by that Interface.

13.4 Interface Variables

A variable whose type is an Interface may reference any object implementing that Interface.

13.5 Generic Interfaces

Interfaces may declare generic parameters.

13.6 Interface Compatibility

Compatibility between an Interface and an implementing type is determined entirely during compilation.

13.7 Summary

Interfaces define behaviour independently of implementation.

Chapter 14. Enumerations

14.1 General

An Enumeration defines a distinct type consisting of a finite set of named values.

14.2 Enumeration Declarations

An Enumeration declaration introduces the Enumeration type and one or more enumerators.

14.3 Enumerator Values

Each enumerator possesses an associated value.

14.4 Type Safety

An Enumeration is a distinct type.

14.5 Comparison

Enumeration values of the same Enumeration type may be compared.

14.6 Summary

Enumerations define finite sets of named constants and improve both readability and type safety.

Chapter 15. Delegates

15.1 General

A Delegate defines a type that represents a callable routine.

Unlike a Function or Sub declaration, which defines executable code, a Delegate describes the signature of a routine. A Delegate value may refer to any Function or Sub whose signature is compatible with the Delegate declaration.

Delegates enable routines to be passed as arguments, stored in variables, returned from Functions, and invoked indirectly.


15.2 Delegate Declarations

A Delegate declaration introduces a new delegate type.

A Delegate specifies:

A Delegate declaration does not provide an implementation.


15.3 Delegate Compatibility

A routine is compatible with a Delegate when:

Compatibility is determined during compilation.


15.4 Delegate Values

A variable of Delegate type contains a reference to a callable routine.

The referenced routine may be invoked through the Delegate exactly as though it had been invoked directly.

The semantics of the invocation remain unchanged.


15.5 Invocation

Invoking a Delegate transfers control to the routine currently represented by the Delegate.

Arguments are evaluated according to the normal routine invocation rules.

For a Function Delegate, invocation produces a value.

For a Sub Delegate, invocation performs an action and produces no value.


15.6 Generic Delegates

A Delegate may declare one or more generic type parameters.

Generic Delegates participate fully in the generic programming facilities of the language.

Type inference may be applied where sufficient information is available.


15.7 Assignment

A Delegate variable may be assigned any compatible routine.

Attempting to assign an incompatible routine is a compile-time error.


15.8 Lifetime

A Delegate remains valid for as long as the referenced routine remains valid according to the execution model of the language.

The precise representation of Delegate values is implementation-defined.


15.9 Summary

Delegates provide type-safe references to executable routines.

They form the foundation for callback-based programming, event handling, and higher-order algorithms.