Learn Ball

Everything you need to understand, build, and extend the Ball programming language.

Overview

What is Ball?

Ball is a programming language where every program is a Protocol Buffer message. Instead of text files that are parsed into ASTs, your code starts as structured data β€” a protobuf message that can be serialized, stored in databases, sent over gRPC, inspected, transformed, and compiled to any target language.

The language schema is defined in a single file: proto/ball/v1/ball.proto. This proto file is the canonical source of truth for what a valid Ball program looks like.

Core Design

Design principles

1. One input, one output per function

Every function takes a single input message and returns a single output message, following the gRPC pattern. This is not a limitation β€” it IS the design. Multiple parameters are expressed as fields of the input message.

2. Code is protobuf messages

The entire AST β€” expression tree, modules, functions, types β€” is defined in ball.proto. Programs can be serialized to binary protobuf or JSON. If it deserializes, it’s structurally valid.

3. Semantic vs. cosmetic boundary

The expression tree, function signatures, type descriptors, and module structure are semantic. Everything else (visibility, mutability, annotations, syntax sugar) is cosmetic metadata. A Ball program with all metadata stripped computes the same result.

4. Base functions have no body

Base functions are declared with isBase: true and have no body expression. Their implementation is provided by each target language’s compiler/engine. This is the extensibility mechanism.

5. Control flow is function calls

if, for, while, switch, try β€” they’re all std base functions. This keeps the language uniform. Compilers must handle them with lazy evaluation (don’t evaluate all branches before choosing one).

6. Types use protobuf descriptors

Ball does NOT invent its own type system. It uses google.protobuf.DescriptorProto and FieldDescriptorProto, which already define how types map to every target language’s native types.

Program Structure

Anatomy of a Ball program

A Ball program is a Program protobuf message that contains modules, which contain functions, types, constants, and imports.

Program structure (pseudo)protobuf
Program
 β”œβ”€β”€ name, version, entryModule, entryFunction
 └── modules[]
      β”œβ”€β”€ name, description
      β”œβ”€β”€ types[]           (google.protobuf.DescriptorProto)
      β”œβ”€β”€ typeDefs[]        (TypeDefinition)
      β”œβ”€β”€ typeAliases[]     (TypeAlias)
      β”œβ”€β”€ enums[]           (google.protobuf.EnumDescriptorProto)
      β”œβ”€β”€ moduleConstants[] (Constant)
      β”œβ”€β”€ functions[]       (FunctionDefinition)
      └── moduleImports[]   (ModuleImport)
Expression Tree

The seven expression types

Every Ball computation is one of seven expression types. This is the core of the language:

ExpressionMeaningExample
call Function call {module, function, input}
literal Constant value int, double, string, bool, bytes
reference Variable reference "input" = function parameter
fieldAccessField access{object, field}
messageCreation Construct message {typeName, fields[]}
block Statement block let-bindings + result expression
lambdaAnonymous functionClosures

Blocks contain Statements (either LetBinding or bare Expression) followed by a result expression. LetBindings bind a name to a value with optional metadata (type, mutability: var/final/const).

Standard Library

Built-in modules

Ball comes with a comprehensive standard library. All standard library functions are base functions β€” their implementation is provided by each target language.

ModuleFunctionsDescription
std ~120 Arithmetic, comparison, logic, bitwise, string, math, control flow, type ops
std_collections~43List and Map operations
std_io~10Console, process, time, random, environment
std_memory~30Linear memory (C/C++ interop)
dart_std ~18 Dart-specific: cascade, null_aware_access, invoke, spread

std module highlights

Arithmetic add, subtract, multiply, divide, divide_double, modulo, negate
Comparison equals, not_equals, less_than, greater_than, lte, gte
Logicaland, or, not
Bitwise bitwise_and, bitwise_or, bitwise_xor, bitwise_not, left_shift, right_shift
Strings string_length, string_contains, string_substring, string_replace, string_split, string_trim, string_to_upper, ...
Math math_abs, math_sqrt, math_pow, math_sin, math_cos, math_pi, math_e, math_clamp, ...
Regex regex_match, regex_find, regex_find_all, regex_replace, regex_replace_all
Control Flow if, for, for_in, while, do_while, switch, try, return, break, continue, throw, rethrow
Type Opsis, is_not, as
Null Safety null_coalesce, null_check
Asyncyield, await
Module System

Dependencies and imports

Ball supports resolving dependencies from four source types:

  • HTTP/HTTPS β€” download from any URL
  • File β€” local filesystem path
  • Inline β€” raw protobuf bytes or JSON embedded in the import
  • Git β€” repository at a specific ref

Each import supports a SHA-256 integrity hash for supply-chain security.

Metadata

Cosmetic metadata system

All metadata is cosmetic β€” it improves round-trip fidelity but doesn’t change computation. Key metadata fields include:

  • FunctionDefinition: kind (function/method/constructor/getter/setter/operator), params, visibility, is_async, is_static, annotations, type_params
  • TypeDefinition: kind (class/struct/interface/mixin/enum/sealed_class), superclass, interfaces, mixins, fields, is_abstract
  • LetBinding: type, mutability, is_final, is_const, is_late
  • Module: language-specific imports (dart_imports, cpp_includes, python_imports, go_imports, etc.)
Getting Started

Quick start guide

Clone the repository and try the Dart implementation:

# Clone Ball
git clone https://github.com/Ball-Lang/ball.git
cd ball

# Install Dart dependencies
cd dart && dart pub get

# Run the engine tests
cd engine && dart test

# Compile an example to Dart
cd ../compiler
dart run bin/compile.dart \
  ../../examples/hello_world.ball.json

# Build the C++ implementation
cd ../../cpp/build && cmake .. && cmake --build .

The proto schema is published on Buf: buf.build/ball-lang/ball