spasiu-funcy
v0.1.3
Published
Funcy - A purely functional language that compiles to TypeScript and JavaScript
Maintainers
Readme
Funcy
A purely functional, expression-oriented language that compiles to JavaScript with runtime type validation.
Overview
Funcy is designed to eliminate mutation, coercion, and imperative control flow while retaining practical interoperability with the JavaScript ecosystem. All evaluation is eager and left-to-right, all values are immutable, and all logic is expressed through functions rather than statements.
📖 Complete Language Reference - Comprehensive guide to Funcy syntax, semantics, and features
🔍 Type Checking Guide - Runtime type validation with Zod
⚡ CLI Documentation - Command-line tools for compiling and running Funcy programs
Features
- Pure Functional: No mutation, no side effects (except I/O)
- Expression-Oriented: Everything is an expression that returns a value
- Type Safe: Optional type annotations with compile-time and runtime validation via Zod
- Recursive Optimization: Recursive functions are automatically optimized into loops
- Multiple Return Values: Functions can return multiple values as arrays
- Structural Equality: Deep equality checking for all data structures
- Error Handling: Automatic error propagation with capture/throw
- Async Support: Promise-based async with
$await operator - Module System: Namespace-based modules with exports
Installation
npm install
npm run buildQuick Reference
| Feature | Syntax | Example |
|---------|--------|----------|
| Variable | @name value; | @x 42; |
| Function | @name params => expr; | @add x, y => x + y; |
| If expression | if(cond, then, else) | if(x > 0, x, 0) |
| Recursion | * (self-reference) | @fact n => if(n = 0, 1, n * *(n - 1)); |
| Array | [1, 2, 3] | @nums [1, 2, 3]; |
| Map | [key: val, ...] | @person [name: "Alice", age: 30]; |
| Multiple returns | => val1, val2, ... | @ops x, y => x + y, x - y; |
| Equality | a = b (structural) | [1, 2] = [1, 2] (true) |
| Member access | Module.function() | Array.map(list, fn) |
| Await | $promise | @result $fetch(); |
| Comment | // comment | // This is a comment |
CLI Commands:
| Command | Description |
|---------|-------------|
| funcy run file.fu | Compile and run immediately |
| funcy compile file.fu | Compile to JavaScript |
| funcy compile folder/ | Bundle folder to single JS file |
See LANGUAGE_REFERENCE.md for complete details.
Usage
CLI Commands
# Run a Funcy file (compile and execute)
funcy run <file.fu>
# Compile a single file to JavaScript
funcy compile <file.fu> [output.js]
# Compile entire folder to single bundle
funcy compile <folder> [output.js]
# Show help
funcy helpExamples:
# Run a program
funcy run examples/hello.fu
# Compile single file
funcy compile src/main.fu dist/main.js
# Compile project folder
funcy compile src/ dist/bundle.jsLanguage Syntax
Variables
@x 42;
@message "Hello, World!";
@numbers [1, 2, 3];
@person [name: "Alice", age: 30];Functions
// Simple function
@add x, y => x + y;
// Function with type annotations
@multiply x:int, y:int => x * y;
// Multiple return values
@math_ops x, y => x + y, x - y, x * y, x / y;
// Using multiple return values
@sum, @diff, @prod, @quot math_ops(10, 5);
// Multi-line function
@compute x => {
@doubled x * 2;
@result doubled + 10;
};Recursion
Recursive functions use * to reference themselves and are automatically optimized into loops:
@factorial n => if(n = 0, 1, n * *(n - 1));
@result factorial(5); // 120Control Flow
Use if as an expression (ternary in compiled JS):
@max a, b => if(a > b, a, b);
@status n => if(n > 0, "positive", if(n = 0, "zero", "negative"));Arrays and Maps
// Arrays
@numbers [1, 2, 3, 4, 5];
@first at(numbers, 0);
@doubled map(numbers, n => n * 2);
// Maps (objects)
@person [name: "Bob", age: 25];
@name Map.get(person, "name");
@updated Map.set(person, "age", 26);Error Handling
// Capture errors
@error, @result capture({
@data risky_operation();
log(data);
});
// Throw errors
@validate x => if(x < 0, throw("negative value"), x);Async Operations
// Await promises with $
@error, @response $IO.get("https://api.example.com");
// Subscribe to events
%my_event error, response => if(exists(error), log(error), log(response));
// Trigger events
&my_event get("https://...");Standard Library
Core Functions
exists(value)- Check if value is not nulllog(...values)- Log and return value(s)if(condition, consequent, alternate)- Conditional expressionthrow(error)- Throw an errorcapture(fn, handler?)- Capture errorslength(arr|str)- Get lengthat(arr, index)- Array accessappend(arr, value)- Append to array (returns new array)
Array Module
Array.map(arr, fn)- Map function over arrayArray.filter(arr, fn)- Filter arrayArray.reduce(arr, fn, initial)- Reduce arrayArray.slice(arr, start, end?)- Slice arrayArray.concat(arr1, arr2)- Concatenate arraysArray.join(arr, separator)- Join array elementsArray.reverse(arr)- Reverse arrayArray.sort(arr, compareFn?)- Sort arrayArray.find(arr, predicate)- Find elementArray.includes(arr, value)- Check inclusionArray.indexOf(arr, value)- Find index
Map Module
Map.get(map, key)- Get value by keyMap.set(map, key, value)- Set key-value pairMap.has(map, key)- Check if key existsMap.keys(map)- Get all keysMap.values(map)- Get all valuesMap.entries(map)- Get key-value pairsMap.delete(map, key)- Delete keyMap.merge(map1, map2)- Merge two maps
String Module
String.length(str)- Get lengthString.at(str, index)- Get characterString.slice(str, start, end?)- Slice stringString.concat(str1, str2)- Concatenate stringsString.split(str, separator)- Split stringString.toLowerCase(str)- Convert to lowercaseString.toUpperCase(str)- Convert to uppercaseString.trim(str)- Trim whitespaceString.replace(str, search, replacement)- Replace substringString.includes(str, search)- Check inclusionString.startsWith(str, prefix)- Check prefixString.endsWith(str, suffix)- Check suffixString.indexOf(str, search)- Find index
IO Module
All IO operations return [error, result] tuples for consistent error handling.
File Operations:
IO.read_file(path)- Read file contents as UTF-8 string →[error, contents]
HTTP Operations:
IO.get(url, options?)- HTTP GET request →[error, response]IO.post(url, body, options?)- HTTP POST request →[error, response]IO.put(url, body, options?)- HTTP PUT request →[error, response]IO.delete(url, options?)- HTTP DELETE request →[error, response]IO.patch(url, body, options?)- HTTP PATCH request →[error, response]IO.head(url, options?)- HTTP HEAD request →[error, response]
Examples
See the examples/ directory for working examples:
hello.fu- Simple hello worldfactorial.fu- Recursive factorial with optimizationarrays.fu- Array operations with map and reducecomprehensive.fu- Comprehensive example showcasing multiple language features
Compile and run any example:
node dist/cli.js examples/hello.fu
node examples/hello.jsArchitecture
The Funcy compiler consists of:
- Lexer (
src/lexer.ts) - Tokenizes Funcy source code - Parser (
src/parser.ts) - Builds an Abstract Syntax Tree (AST) - Code Generator (
src/codegen.ts) - Generates JavaScript from AST - Runtime (
src/runtime.ts) - Core runtime library and standard functions - CLI (
src/cli.ts) - Command-line interface for compilation
Compilation Process
Funcy Source (.fu) → Lexer → Parser → AST → Code Generator → JavaScript (.js)The generated JavaScript uses the Funcy runtime library for:
- Structural equality checking
- Error handling with capture/throw
- Standard library functions
- Type validation (future: with Zod schemas)
Testing
# Run compiler tests
npm test
# Run type checking tests
npm run test:typesThe test suites cover:
- Compiler tests: Variable declarations, functions, recursion, control flow
- Type checking tests: Runtime type validation with Zod for all supported types (int, string, bool, array, map)
Language Design Principles
- No Mutation: All data structures are immutable
- No Coercion: Strict type checking, no implicit conversions
- Expression-Only: No statements, everything returns a value
- Eager Evaluation: Left-to-right evaluation order
- Structural Typing: Types match by structure, not name
- Fail Fast: Errors propagate unless explicitly captured
Future Enhancements
- Lambda expressions (anonymous functions)
- Pattern matching
- Zod schema generation for runtime type validation
- TypeScript output with full type annotations
- More comprehensive standard library
- IDE/Editor support with syntax highlighting
- REPL for interactive development
- Package management system
- WebAssembly compilation target
License
MIT
