Menu

Language Core

Relevant source files

This document provides a deep dive into the OwnLang language processing pipeline from source code to execution. It covers the complete transformation chain that converts textual source code into executable programs, including lexical analysis, parsing, AST generation, static analysis, and optimization stages.

For information about the runtime value system and function execution, see Function System and Object Model. For details about the module system architecture, see Module System.

Processing Pipeline Architecture

The OwnLang language core implements a multi-stage processing pipeline that transforms source code through several distinct phases before execution.

Core Pipeline Flow

Sources: ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java37-48 ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java44-59

Stage Components and Responsibilities

The processing pipeline consists of several key stages, each implemented as a Stage<Input, Output> interface:

StageInput TypeOutput TypePrimary Responsibility
SourceLoaderStageInputSourceStringLoad source code from files/resources
LexerStageStringList<Token>Tokenize source into lexemes
ParserStageList<Token>NodeGenerate Abstract Syntax Tree
LinterStageNodeNodePerform static analysis and validation
OptimizationStageNodeNodeApply AST transformations and optimizations
ExecutionStageNodeValueExecute the program

Sources: ownlang-core/src/main/java/com/annimon/ownlang/util/input/SourceLoaderStage.java11-29 ownlang-parser/src/main/java/com/annimon/ownlang/stages/ParserStage.java11-29

Input Processing and Source Loading

InputSource System

The language core supports multiple input sources through the InputSource interface, enabling loading from files, resources, and other sources.

The InputSourceDetector handles path resolution and determines whether to load from filesystem or classpath resources based on the resource: prefix.

Sources: ownlang-core/src/main/java/com/annimon/ownlang/util/input/InputSource.java5-16 ownlang-core/src/main/java/com/annimon/ownlang/util/input/InputSourceDetector.java6-39

Source Loading and Preprocessing

The SourceLoaderStage performs initial source processing and metadata extraction:

  • Loads source code as UTF-8 strings
  • Splits content into lines for error reporting
  • Extracts base path for relative include resolution
  • Stores metadata in StagesData for downstream stages

Sources: ownlang-core/src/main/java/com/annimon/ownlang/util/input/SourceLoaderStage.java16-29

Lexical Analysis

Token Generation Process

The Lexer class implements a character-by-character scanner that converts source text into a sequence of tokens. The lexer recognizes several token categories:

Token Types and Operators

The lexer maintains static mappings for operators and keywords to enable efficient recognition:

  • Operators Map: Maps character sequences to TokenType values (e.g., "=="TokenType.EQEQ)
  • Keywords Map: Maps reserved words to keyword tokens (e.g., "def"TokenType.DEF)
  • Number Recognition: Supports integers, decimals, hex numbers, and long suffixes

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/Lexer.java21-111 ownlang-parser/src/main/java/com/annimon/ownlang/parser/Lexer.java157-245

Position Tracking and Error Reporting

The lexer maintains precise position information for each token, tracking row and column numbers. This enables accurate error reporting and source location mapping:

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/Lexer.java405-447 ownlang-parser/src/test/java/com/annimon/ownlang/parser/LexerPositionsTest.java12-63

Syntax Analysis and AST Generation

Recursive Descent Parser

The Parser class implements a recursive descent parser that converts the token stream into an Abstract Syntax Tree. The parser uses operator precedence and left-to-right associativity rules.

Expression Precedence Hierarchy

The parser implements operator precedence through the method call hierarchy, with higher precedence operators parsed deeper in the call stack:

  1. Assignment: =, +=, -=, etc.
  2. Ternary: ?: conditional operator
  3. Logical OR: ||
  4. Logical AND: &&
  5. Bitwise OR: |
  6. Bitwise XOR: ^
  7. Bitwise AND: &
  8. Equality: ==, !=
  9. Relational: <, <=, >, >=
  10. Shift: <<, >>, >>>
  11. Additive: +, -, ::
  12. Multiplicative: *, /, %, **
  13. Unary: +, -, !, ~, ++, --
  14. Primary: literals, identifiers, function calls

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java508-797

Error Recovery and Resilience

The parser implements error recovery to continue parsing after encountering syntax errors:

The recovery mechanism advances through tokens until it finds a position where parsing can continue successfully.

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java105-118 ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java87-102

Static Analysis and Validation

Linter Architecture

The LinterStage provides configurable static analysis with multiple validation modes:

Validator Components

Each validator implements the Visitor pattern to traverse the AST and check for specific issues:

  • IncludeSourceValidator: Validates that included files exist and are readable
  • LoopStatementsValidator: Ensures break/continue statements appear within loops
  • AssignValidator: Checks for assignment patterns and variable usage
  • DefaultFunctionsOverrideValidator: Warns about overriding built-in functions

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/LinterStage.java15-65 ownlang-parser/src/main/java/com/annimon/ownlang/parser/linters/IncludeSourceValidator.java11-34

Optimization and Transformation

AST Optimization Pipeline

The OptimizationVisitor applies transformation passes to optimize the AST before execution:

Transformation Strategy

The optimization visitor implements a bottom-up traversal strategy, processing child nodes before their parents. This ensures that optimizations cascade upward through the expression tree.

Key optimization techniques include:

  • Constant Folding: Evaluate constant expressions at compile time
  • Variable Inlining: Replace variable references with constant values where possible
  • Dead Code Removal: Eliminate unreachable statements
  • Function Inlining: Expand simple function calls inline

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java10-479 ownlang-parser/src/main/java/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java40-46

Include System and Module Loading

Dynamic Include Processing

The IncludeStatement enables runtime file inclusion with support for both filesystem and classpath resources:

The include system creates a complete processing pipeline for each included file, enabling recursive includes and maintaining proper scope isolation.

Sources: ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/IncludeStatement.java25-60 ownlang-core/src/main/java/com/annimon/ownlang/util/input/InputSourceDetector.java24-32