AIFPL is possibly one of the first programming languages designed specifically for use by an LLM rather than a human. It's a Lisp-inspired, higher-order, pure functional language, making a conscious decision to forgo regular I/O operations to ensure it is always safe for an AI to use, without having to worry about potential security problems.
While the functional style can be quite challenging for human developers, LLMs are surprisingly adept with this type of software development.
The code is currently integrated within Humbug but is designed to stand alone. It is implemented in Python, but has no dependencies other than the Python standard library.
Design Principles
- Pure List Representation: Everything is data, following traditional Lisp philosophy
- Functional Programming: First-class functions, immutable data, no side effects
- Lexical Scoping: Variables resolved in their definition environment
- Tail Call Optimization: Automatic optimization for recursive patterns
- Type Safety: Comprehensive type hints and strict type checking
- Error Handling: Detailed error messages with position information
- Performance: Efficient evaluation with automatic optimizations
- LISP Compatibility: Following traditional LISP semantics where applicable
- Lazy Evaluation: Conditionals and boolean operators use lazy evaluation
- Independence: No dependencies on external packages
- Simplicity: Direct S-expression evaluation without over-engineering
- Homoiconicity: Code and data use identical representations
- Syntactic Sugar: Single quote shortcut provides convenient syntax while maintaining pure list representation
Architecture
AIFPL uses a pure list representation for all code, following traditional Lisp philosophy:
- Everything is data: Code and data have identical representation (AIFPLValue objects)
- No special AST nodes: Lambda expressions, let expressions, and function calls are all just lists
- Homoiconic: The same data structures represent both code and data
- Simple and consistent: One unified representation for all expressions
- Traditional Lisp semantics: Everything is data, following Lisp philosophy
Type System
AIFPL has a strict type system with the following types:
- Numbers: int, float, complex (with automatic promotion)
- Strings: UTF-8 strings with no automatic conversion
- Booleans: #t and #f with no automatic conversion
- Lists: Heterogeneous collections supporting any element type
- Functions: First-class lambda functions with lexical scoping
Implementation
AIFPL has been implemented with the following considerations:
- Written in Python: Easy to read and modify, with no external dependencies
- Correct by design: AIs will rely on this language to implement ad-hoc sequences of logic, so correctness is paramount
- Thoroughly tested: To help ensure correctness, AIFPL has extensive unit tests. These cover 100% of all statements and branches in the codebase
- Optimization: Performance is not the primary goal. Optimization work is being deferred until more data on usage emerges.
- Runtime error handling: AIFPL provides detailed error messages with position information to help diagnose issues. This is especially important when AIs are generating code on the fly.
Basic Examples
Arithmetic Operations
; Basic arithmetic
(+ 1 2 3) ; → 6
(- 10 3) ; → 7
(* 2 3 4) ; → 24
(/ 12 3) ; → 4
(// 7 3) ; → 2 (floor division)
(% 7 3) ; → 1 (modulo)
(** 2 3) ; → 8 (exponentiation)Quote - Data Literals and Code as Data
; Without quote - expression gets evaluated
(+ 1 2 3) ; → 6
; With quote - expression returned as data
(quote (+ 1 2 3)) ; → (+ 1 2 3)
'(+ 1 2 3) ; → (+ 1 2 3) (shortcut form)
; Create lists as pure data
'(1 2 3) ; → (1 2 3)
'((a 1) (b 2) (c 3)) ; → ((a 1) (b 2) (c 3))
; Mix quoted and unquoted in larger expressions
(list 'hello (+ 1 2) 'world) ; → (hello 3 world)Lambda Functions
; Simple lambda functions
((lambda (x) (* x x)) 5) ; → 25
((lambda (x y) (+ x y)) 3 4) ; → 7
; Lambda functions as values
(let ((square (lambda (x) (* x x))))
(square 6)) ; → 36
; Higher-order function usage
(map (lambda (x) (* x x)) (list 1 2 3 4)) ; → (1 4 9 16)
; Closures capture their environment
(let ((multiplier 10))
(let ((times-ten (lambda (x) (* x multiplier))))
(times-ten 5))) ; → 50List Operations
; List construction and manipulation
(list 1 2 3) ; → (1 2 3)
(list 1 "hello" #t) ; → (1 "hello" #t) [mixed types]
(cons 1 (list 2 3)) ; → (1 2 3) [prepend]
(append (list 1 2) (list 3 4)) ; → (1 2 3 4) [concatenate]
; List access and properties
(first (list 1 2 3)) ; → 1
(rest (list 1 2 3)) ; → (2 3)
(length (list 1 2 3)) ; → 3
(member? 2 (list 1 2 3)) ; → #t
; List utilities
(remove 2 (list 1 2 3 2 4)) ; → (1 3 4)
(position 2 (list 1 2 3)) ; → 1 (0-based index)Higher-Order Functions
; Map - transform each element
(map (lambda (x) (* x 2)) (list 1 2 3 4)) ; → (2 4 6 8)
; Filter - select elements by predicate
(filter (lambda (x) (> x 0)) (list -1 2 -3 4)) ; → (2 4)
; Fold - accumulate results
(fold + 0 (list 1 2 3 4 5)) ; → 15
; Range - generate numeric sequences
(range 1 5) ; → (1 2 3 4)
(range 0 10 2) ; → (0 2 4 6 8)
; Complex data processing pipeline
(let ((numbers (range 1 11)))
(let ((evens (filter (lambda (x) (= (% x 2) 0)) numbers))
(squared (map (lambda (x) (* x x)) evens))
(sum (fold + 0 squared)))
sum)) ; → 220Type Predicates
; Basic type checking
(number? 42) ; → #t
(string? "hello") ; → #t
(boolean? #t) ; → #t
(list? (list 1 2 3)) ; → #t
(function? (lambda (x) (* x 2))) ; → #t
; Specific numeric type checking
(integer? 42) ; → #t
(float? 3.14) ; → #t
(complex? (+ 1 j)) ; → #t
; Polymorphic operations with type checking
(let ((safe-process (lambda (value)
(if (number? value)
(* value value)
(if (string? value)
(string-upcase value)
"unknown type")))))
(map safe-process (list 5 "hello" #t))) ; → (25 "HELLO" "unknown type")String Operations
; String construction and manipulation
(string-append "hello" " " "world") ; → "hello world"
(string-length "hello") ; → 5
(string-upcase "hello") ; → "HELLO"
(string-downcase "HELLO") ; → "hello"
; String searching and testing
(string-contains? "hello world" "world") ; → #t
(string-prefix? "hello" "he") ; → #t
(string-suffix? "hello" "lo") ; → #t
; String-list conversion
(string->list "hello") ; → ("h" "e" "l" "l" "o")
(list->string (list "h" "i")) ; → "hi"
; String splitting and joining
(string-split "name,age,city" ",") ; → ("name" "age" "city")
(string-join (list "hello" "world") " ") ; → "hello world"
; Advanced text processing
(let ((clean-and-format (lambda (text)
(let ((trimmed (string-trim text))
(normalized (string-replace trimmed " " " ")))
(string-upcase normalized)))))
(clean-and-format " hello world ")) ; → "HELLO WORLD"Complex Numbers
; Complex number construction
(complex 3 4) ; → (3+4j)
(+ 1 (* 2 j)) ; → (1+2j)
; Extract real and imaginary parts
(real (complex 3 4)) ; → 3
(imag (complex 3 4)) ; → 4
; Works with all numeric types
(real 42) ; → 42
(imag 42) ; → 0
(real 3.14) ; → 3.14
(imag j) ; → 1
; Complex arithmetic
(+ (complex 1 2) (complex 3 4)) ; → (4+6j)
(* j j) ; → -1
(sqrt -1) ; → jSymbolic Programming with Quote
; Manipulate code structure
(let ((expr '(+ a b c)))
(first expr)) ; → + (the operator symbol)
; Build expressions programmatically
(let ((op '+)
(args '(1 2 3)))
(cons op args)) ; → (+ 1 2 3)
; Template-based code generation
(let ((make-adder (lambda (n)
(list 'lambda
'(x)
(list '+ 'x n)))))
(make-adder 5)) ; → (lambda (x) (+ x 5))
; Code transformation
(let ((transform-ops (lambda (expr)
(if (list? expr)
(map transform-ops expr)
(if (= expr '+)
'*
expr)))))
(transform-ops '(+ 1 (+ 2 3)))) ; → (* 1 (* 2 3))Advanced Features
Tail Call Optimization
AIFPL automatically optimizes tail calls to prevent stack overflow in recursive functions:
; Factorial with tail recursion (automatically optimized)
(let ((factorial (lambda (n acc)
(if (<= n 1)
acc
(factorial (- n 1) (* n acc))))))
(factorial 1000 1)) ; Works with large numbers
; Mutual recursion is also optimized
(let ((is-even (lambda (n)
(if (= n 0) #t (is-odd (- n 1)))))
(is-odd (lambda (n)
(if (= n 0) #f (is-even (- n 1))))))
(is-even 10000)) ; → #t (no stack overflow)Functional Data Processing
; Multi-step data processing pipeline
(let ((numbers (range 1 21)))
(let ((evens (filter (lambda (x) (= (% x 2) 0)) numbers))
(squares (map (lambda (x) (* x x)) evens))
(sum (fold + 0 squares)))
sum)) ; → 1540
; Text processing pipeline
(let ((text "The Quick Brown Fox"))
(let ((words (string-split (string-downcase text) " "))
(long-words (filter (lambda (w) (> (string-length w) 3)) words))
(capitalized (map string-upcase long-words)))
(string-join capitalized "-"))) ; → "QUICK-BROWN"
; Data validation and transformation
(let ((validate-and-double (lambda (nums)
(if (all? (lambda (x) (> x 0)) nums)
(map (lambda (x) (* x 2)) nums)
"error: negative numbers"))))
(list (validate-and-double (list 1 2 3))
(validate-and-double (list 1 -2 3)))) ; → ((2 4 6) "error: negative numbers")More Information
AIFPL is currently integrated within the Humbug project. You can find the source code and more information at:
- GitHub repository: https://github.com/m6r-ai/humbug
- The AIFPL implementation can be found in the
aifpldirectory of the Humbug repository