Language overview

Neo language overview.

The repository README, current compiler behavior, recent runtime additions, and the interpreter written in Neo.

Edition Neo 3.1License Apache 2.0View repository ↗

Neo

One vector model for data, functions, code, uncertainty, and native computation.

Neo is a vector-native programming language.

In Neo, vectors are not containers added to a scalar language. They are the foundation of the language itself. Data are vectors. Functions operate through vectors. Code is represented as vectors. Arithmetic, logic, control flow, statistics, matrices, and AI operations all follow the same computational model.

Write an operation once, apply it to one value or millions, and compile the result into a native executable.

{var sensor-values [42.1 43.5 ? 46.0]}

{def calibrate (x)
  {+ {* x 0.98} 1.2}}

{var calibrated {calibrate sensor-values}}

{print
  {if {< calibrated 45}
    "normal"
    "hot"
    "unknown"}}

Output:

["normal" "normal" "unknown" "hot"]

There is no loop, no map, no nullable wrapper, and no separate array API.

The scalar calibrate function automatically operates over the entire vector. The comparison is vectorized. The if expression evaluates element by element. Unknown sensor data follows its own branch.

That is the core of Neo: high-level vector computation with native execution.


Everything is a vector

Neo begins with one idea:

Computation is vector transformation.

The language does not separate ordinary values, collections, functions, and programs into unrelated worlds.

[1 2 3 4]                    ; homogeneous data

(name:"Neo" version:3)       ; heterogeneous dictionary data

{+ 1 2}                      ; executable code

Homogeneous vectors use [].

Heterogeneous data and dictionaries use ().

Executable vectors use {}.

Functions and operations participate in the same evaluation model, allowing scalar, vector, matrix, and multidimensional computation to share the same notation.


One definition, every scale

A Neo function does not need separate scalar and vector versions.

{def square (x)
  {* x x}}

{square 5}
; 25

{square [1 2 3 4]}
; [1 4 9 16]

The function describes the operation itself. Neo determines how it travels across the data.

{def affine (x scale bias)
  {+ {* x scale} bias}}

{affine 5 2 1}
; 11

{affine [1 2 3 4] 2 1}
; [3 5 7 9]

Scalar values broadcast naturally:

{+ [1 2 3] 10}
; [11 12 13]

Vectors interact element by element:

{* [1 2 3] [10 20 30]}
; [10 40 90]

Nested vectors extend the same model into matrices and higher-dimensional data.

Neo does not require map, foreach, manual indexing, or a separate vectorization API for ordinary operations.


Data analysis that becomes an executable

Neo combines data-analysis capabilities with a native compilation model.

A program can read data, transform vectors, handle missing values, compute statistics, perform matrix operations, and produce a standalone executable.

{var samples [12.5 15.0 ? 18.5 21.0]}

{def center (x average)
  {- x average}}

{var average {mean samples}}
{var centered {center samples average}}

{print centered}

Neo includes operations for:

  • filtering and reduction
  • sorting and searching
  • statistical analysis
  • dictionaries and structured data
  • JSON conversion
  • matrices and linear algebra
  • set operations
  • file input and output
  • numerical transformations
  • missing-data processing

The goal is not merely to explore data interactively. Neo programs can be compiled, deployed, and executed as native applications.


Unknown is part of the language

Incomplete data is not pushed into a library wrapper or represented with an arbitrary sentinel value.

Neo has a first-class unknown value:

?

Errors are also first-class values:

!

Unknown values can exist inside ordinary vectors:

{var readings [21.4 ? 22.8 23.1]}

They participate in arithmetic, comparisons, logic, statistics, and control flow according to defined language semantics.

{missing? ?}
; T

{missing? 42}
; F

Neo also provides strict propagation operations for calculations where an unknown input must produce an unknown result.

This makes uncertainty visible in the program rather than hiding it behind exceptions, special numbers, or secondary validity arrays.


Three-way control flow

A condition in real computation is not always simply true or false.

It may also be unknown.

Neo therefore gives if three result branches:

{if condition
  true-result
  false-result
  unknown-result}

Example:

{var temperature ?}

{print
  {if {< temperature 40}
    "safe"
    "too hot"
    "sensor unavailable"}}

Output:

sensor unavailable

The unknown branch is not an afterthought. It is part of the control-flow model.


Vectorized control flow

Neo’s if expression also operates directly over vectors.

{if [T F ?]
  [10 20 30]
  [1 2 3]
  [100 200 300]}

Result:

[10 2 300]

Each condition selects the corresponding true, false, or unknown value.

Scalar branches can also broadcast:

{var values [4 -2 ? 7]}

{if {> values 0}
  "positive"
  "non-positive"
  "unknown"}

Result:

["positive" "non-positive" "unknown" "positive"]

There is no need to write a loop around the condition or manually combine masks.


Pairwise computation or every combination

Normal vector operations are element-wise:

{+ [1 2 3] [10 20 30]}
; [11 22 33]

The @ spread operator requests the Cartesian product instead:

{+ @[1 2] @[10 20 30]}

Result:

[[11 21 31]
 [12 22 32]]

The same idea works with user-defined functions:

{def distance (x y)
  {abs {- x y}}}

{distance @[1 5 10] @[2 8]}

Result:

[[1 7]
 [3 3]
 [8 2]]

One spread vector produces one-dimensional expansion. Two spread vectors produce a matrix. Additional spread vectors naturally produce higher-dimensional results.

Nested loops become part of the expression rather than control-flow machinery surrounding it.


Numerical computing is built in

Neo includes numerical types and operations as language-level capabilities rather than requiring a collection of disconnected packages.

Statistics

{mean values}
{variance values}
{sd values}
{min values}
{max values}

Matrices

{matmul A B}
{transpose A}
{outer x y}
{identity 4}
{diagonal values}
{trace A}

Complex numbers

{var z (3 4i)}

{abs z}
; 5

Quaternions

{var rotation (1 0i 0j 0k)}

{quat-normalize rotation}
{quat-rotate rotation vector}

Complex numbers and quaternions use their mathematical operations directly and integrate with Neo’s broader vector model.


AI operations without framework ceremony

Neo includes foundational AI and numerical-learning operations:

{relu values}
{sigmoid values}
{softmax logits}

{mse prediction target}
{cross-entropy prediction target}

Combined with vectors, matrices, statistics, Cartesian expansion, and native compilation, these primitives can be used for compact inference pipelines and numerical models.

{def layer (input weights bias)
  {relu {+ {matmul input weights} bias}}}

Neo is not tied to a single external AI framework. Its numerical operations are part of the runtime and can also be extended through C and C++ libraries.


Designed for robotics, edge systems, and small processors

Neo aims to combine high-level vector expressions with predictable native execution.

It is designed for work such as:

  • robotics and control systems
  • sensor processing
  • peripheral and device interaction
  • signal processing
  • edge inference
  • embedded numerical applications
  • game physics
  • real-time data transformation
  • small and resource-constrained processors

The C and C++ ecosystem remains available

A new language should not require its users to rebuild decades of systems software.

Neo can include C and C++ source files and connect to external libraries through its foreign-function interface.

{include "robot_driver.cpp"}
{include "signal_processing.cpp"}

A wrapper can expose existing library functionality as normal Neo functions.

// @neo_link opencv_core
// @neo_link opencv_imgproc

This allows Neo programs to work with existing ecosystems such as:

  • hardware drivers
  • operating-system APIs
  • robotics libraries
  • computer-vision libraries
  • numerical libraries
  • networking libraries
  • graphics and game libraries
  • vendor SDKs
  • specialized embedded libraries

Neo provides the computational model. C and C++ provide access to the surrounding world.


Code is also data

Because Neo distinguishes executable vectors {} from heterogeneous data vectors (), code can be stored and manipulated without executing it immediately.

{var pipeline
  ({print "read"}
   {print "transform"}
   {print "write"})}

Stored code can later cross into execution explicitly:

{run pipeline}

The {run} bridge makes that transition visible.

{set pipeline
  {& pipeline
     ({print "complete"})}}

{run pipeline}

Code can therefore be generated, stored, transformed, extended, and executed using the same vector principles as other Neo data.


The Neo model

The central pieces of Neo reinforce one another:

Everything is a vector
        ↓
Scalar functions naturally lift
        ↓
Arithmetic and logic operate over data
        ↓
Unknown values remain inside the computation
        ↓
Control flow becomes three-way and vectorized
        ↓
Cartesian spread expresses multidimensional work
        ↓
Numerical and AI operations share the same model
        ↓
The result compiles into a native executable

Neo is not a scalar language with a vector library attached.

It is a language designed from the vector outward.

Language capabilities

Neo currently provides:

  • one computational model for data, functions, and code
  • automatic scalar-to-vector lifting
  • scalar broadcasting
  • element-wise vector arithmetic
  • Cartesian-product expansion with @
  • homogeneous vectors
  • heterogeneous data vectors
  • dictionary literals and field access
  • first-class unknown ? and error ! values
  • three-way conditional logic
  • vectorized conditional execution
  • functions, lambdas, closures, and recursion
  • ranges and higher-dimensional vectors
  • filtering, reduction, sorting, and searching
  • set operations
  • JSON conversion
  • statistics
  • matrix and linear-algebra operations
  • complex numbers
  • quaternions
  • AI activation and loss functions
  • file and console input/output
  • time utilities
  • Neo modules
  • C and C++ foreign-function integration
  • C++17 code generation
  • deterministic arena-oriented memory facilities

Build the compiler

Requirements

  • CMake 3.10 or newer
  • a C++17 compiler
  • g++ available on PATH
  • Ninja, recommended but optional

On Windows, the MSYS2 UCRT64 toolchain works well.

Build with Ninja

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build

Build with the default CMake generator

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

The compiler is created at:

build/neo.exe    Windows
build/neo        Unix-like systems

Compile a Neo program

.\build\neo.exe examples\hello.neo hello.exe
.\hello.exe

Compiler syntax:

neo <source.neo> [output] [--opt=0|1|2|3|s|g] [--coverage]

The default optimization level is -O2.

When no output filename is supplied, Neo writes:

<source.neo>.exe

The generated C++ source is emitted as:

<source.neo>.cpp

Generated source files and executables are excluded from Git.


Examples

examples/hello.neo
examples/vector-lifting.neo
examples/vector-if.neo
examples/cartesian-spread.neo
examples/missing-data.neo
examples/dictionaries.neo
examples/statistics.neo
examples/matrix.neo
examples/complex.neo
examples/ai.neo
examples/ffi/

A compact Neo example:

{var input [1 -2 ? 4]}

{def transform (x)
  {relu {* x x}}}

{var output {transform input}}

{print
  {if {> output 0}
    output
    0
    ?}}

The function, arithmetic, activation, comparison, and conditional all operate across the vector without explicit iteration.


Documentation

The current GFM specification is the source of truth for Neo 3.x behavior.

Tests

Compile and run the primary regression suite:

.\build\neo.exe tests\v3\neo-full-regression.neo neo-full-regression.exe
.\neo-full-regression.exe

Create the coverage build:

py -m pip install gcovr

cmake -S . -B build-cov `
  -G Ninja `
  -DNEO_COVERAGE=ON `
  -DCMAKE_BUILD_TYPE=Debug

cmake --build build-cov
.\tools\run_coverage.ps1

Test categories:

tests/v3/coverage/pass/
tests/v3/coverage/compile_fail/
tests/v3/coverage/runtime_fail/
tests/v3/known_failures/

Passing behavior belongs in the regression or coverage suites. Active compiler bugs remain isolated under known_failures until corrected.


Repository layout

include/neo/             runtime headers
src/                     compiler implementation
examples/                Neo programs and FFI examples
tests/v3/                regression and conformance tests
docs/                    language reference and specification
tools/                   build and coverage tools
MIGRATION_NOTES_V3.md    implementation and migration notes

The compiler includes:

UTF-8 lexer
Parser
Abstract syntax tree
Semantic analyzer
C++17 code generator
Runtime library
External compiler driver

Development

Neo is under active development.

The compiler already implements the central vector model, automatic vector operations, dictionaries, functions, three-way conditionals, vectorized control, native C++ generation, and a broad numerical runtime.

Current work is focused on:

  • completing call-by-reference semantics
  • strengthening named-frame break and repeat
  • expanding closure-capture behavior
  • completing vectorized control-flow edge cases
  • improving module loading
  • formalizing arena-memory guarantees
  • increasing specification conformance coverage
  • expanding supported deployment targets

See MIGRATION_NOTES_V3.md for detailed implementation notes.


Contributing

Neo welcomes contributors interested in:

  • compiler construction
  • language design
  • numerical computing
  • runtime development
  • embedded systems
  • robotics
  • data processing
  • AI primitives
  • testing
  • documentation
  • editor tooling
  • C and C++ integration

A compiler or runtime change should include a focused Neo regression test.

Use:

tests/v3/coverage/pass/

for valid programs,

tests/v3/coverage/compile_fail/

for programs the compiler must reject, and

tests/v3/coverage/runtime_fail/

for programs that compile but produce a runtime failure.

When the language specification and compiler behavior differ, document the mismatch rather than weakening the test silently.


Why Neo?

Many languages make you choose between:

  • expressive data analysis and deployable native programs
  • high-level vector computation and hardware access
  • numerical convenience and predictable execution
  • compact code and explicit missing-data behavior
  • built-in operations and access to an existing systems ecosystem

Neo is designed to bring these together.

Vector-native expressions
Native executables
First-class uncertainty
Three-way vector control
Numerical and AI primitives
C and C++ integration
Edge-oriented execution

One language, one computational model.


License

Neo is licensed under the Apache License 2.0.

See LICENSE.

Neo interpreter written in Neo

Neo now includes a complete interpreter implemented in Neo itself.

The interpreter has its own lexer, recursive-descent parser, evaluator, runtime environment, and persistent multiline REPL. It can run a Neo source file and then keep the same environment alive for interactive work.

Neo source
    ↓
Neo interpreter written in Neo
    ↓
Neo program execution

The interpreter runs Neo's full regression suite through interpreted execution:

NEO FULL REGRESSION TEST PASSED

The native compiler remains the primary implementation for performance and executable generation. The interpreter is used as a semantic reference, a compiler-consistency test, an interactive environment, and a foundation for further self-hosting work.


Recent runtime additions

Command-line arguments

Compiled Neo programs can read their command-line arguments with args.

{print {args}}

For a program launched as:

.\program.exe alpha beta

{args} returns the two user arguments as a heterogeneous data vector.

Strings use vector operations

String values now work with the same concatenation and update operations used by vectors.

{& "Neo" " language"}
; "Neo language"

{push "Ne" "o"}
; "Neo"

{pop "Neo"}
; "Ne"

Real and imaginary arithmetic

Real values and imaginary values can be combined directly in multiplication and division.

{* 2 1i}
; 2i

{/ 2i 2}
; 1i