Pulse
Pulse 3.1 A programming language with CSP-style concurrency, structured concurrency, and cooperative scheduling.
Install / Use
/learn @osvfelices/PulseREADME
Pulse 3.1
A programming language with CSP-style concurrency, structured concurrency, and cooperative scheduling.
| Status | Versioning | |--------|------------| | docs/STATUS.md | VERSIONING.md |
Language 1.0: Not yet declared. See What's Missing for Language 1.0.
What is Pulse?
Pulse is a programming language built for concurrent systems programming with:
- Native CSP primitives -
spawn, channels, andselectstatements built into the language - Structured concurrency - Parent tasks automatically manage child task lifecycles
- Cooperative scheduler - Deterministic task execution with predictable behavior
- Optional type system - Gradual typing with
--strict-typesflag - JavaScript interop - Compiles to JavaScript, imports from npm seamlessly
- IR-based compiler - Multi-stage pipeline with dead code elimination and constant folding
Pulse 3.1 includes a new compiler architecture with intermediate representation (IR), semantic analysis, and optional static type checking.
When to Use This
Use Pulse Runtime when you need:
Structured Concurrency
- Parent tasks automatically cancel children when cancelled or when they complete
- No orphaned tasks or background work that outlives its context
- Clear task lifecycles with completion promises
Backpressure and Flow Control
- Channels with bounded buffers to prevent unbounded queuing
- Admission control to reject requests when overloaded
- Load shedding based on queue depth or memory pressure
Deterministic Execution
- Tasks execute in predictable order based on logical time, not wall-clock time
- Same inputs produce same execution order (useful for testing and debugging)
- Batch-then-yield scheduling model
Resource Management
- Per-request resource limits (task count, duration, memory)
- Configurable concurrency pools for HTTP servers
- Memory monitoring with state change events
Production Observability
- Prometheus metrics for tasks, channels, HTTP requests
- Graceful shutdown with timeout support
- Health check endpoints for load balancers
Installation
npm install pulselang
Requires Node.js 18 or higher.
New in Pulse 3.1
M14 Runtime Upgrades
Channel System (M14.1):
- RingBuffer-backed channels with O(1) push/shift operations
- Power-of-two sizing for fast modulo via bitmask
Supervisor Trees (M14.2):
- Restart strategies: one_for_one, one_for_all, rest_for_one
- Automatic child restart with configurable intensity/period
Structured Concurrency v2 (M14.3):
- AsyncGroup with waitWithTimeout using logical time
- Two-phase cancellation marking
Select Engine v2 (M14.5):
- First-winner determinism (lowest ready index wins)
- Cancel-safe semantics with eager cleanup of losing waiters
- No Promise.race, no timers, pure logical-time operation
Compiler Architecture
Multi-Stage Compilation Pipeline:
- Lexer → Parser → AST → Semantic Analysis → Type Checking → IR → Optimization → Backend
Intermediate Representation (IR):
- IR-based backend (default in 3.1.0)
- SSA-form register-based IR with control flow graph
- Dead code elimination and constant folding optimizations
- Full validation pass for IR correctness
- ECMAScript-style completion records for exception handling
Semantic Analysis:
- Variable resolution with scope tracking
- Temporal dead zone (TDZ) detection
- const/let enforcement
- Control flow validation (return/break/continue)
Optional Type System:
- Gradual typing with
--strict-typesflag - Type annotations:
const x: number = 42 - Function signatures:
fn add(a: number, b: number): number - Type checking for annotated code only (unannotated code is never checked)
Compiler Flags
Run Pulse files with the pulse or pulselang CLI:
pulse script.pls # Default: IR backend
pulse script.pls --legacy-backend # Use legacy codegen (fallback)
pulse script.pls --strict-types # Enable type checking
pulse script.pls --strict-semantic # Treat semantic warnings as errors
pulse script.pls --sourcemap # Generate source maps
Available Flags:
--legacy-backend: Use legacy codegen instead of IR (fallback for compatibility)--strict-types: Enable optional static type checking--strict-semantic: Fail on semantic errors (default: warnings)--strict-ast: Enable strict AST validation--sourcemap: Generate inline source maps for debugging
Language Features
Type Annotations (optional, requires --strict-types):
// Variable type annotations
const x: number = 42;
let name: string = "Alice";
// Function signatures
fn add(a: number, b: number): number {
return a + b;
}
// Type checking only applies to annotated code
const untyped = "hello"; // No type checking
Compiler Modes:
- Default: IR-based backend with optimization passes
- Legacy Backend (
--legacy-backend): Original codegen, available as fallback - Type Checked (
--strict-types): Static type checking for annotated code
Quick Start
Basic Task Spawning
import { spawn, sleep } from 'pulselang/runtime';
// Spawn a concurrent task
const task = spawn(async () => {
await sleep(100);
return 'done';
});
// Wait for completion
await task.promise;
console.log(task.result); // 'done'
HTTP Server with Scheduler Pool
import { createServerWithScheduler, spawn, sleep } from 'pulselang/runtime';
const server = createServerWithScheduler(async (req, res) => {
// All Pulse primitives work inside handlers
const task = spawn(async () => {
await sleep(100);
return `Processed ${req.url}`;
});
await task.promise;
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(task.result);
}, {
maxPoolSize: 100, // Max 100 concurrent requests
maxQueueSize: 50, // Max 50 queued when pool full
timeout: 30000 // 30 second request timeout
});
server.listen(3000);
console.log('Server running on port 3000');
Channels and Pipelines
import { spawn, Channel } from 'pulselang/runtime';
const ch = new Channel(10); // Buffered channel with capacity 10
// Producer
spawn(async () => {
for (let i = 0; i < 5; i++) {
await ch.send(i);
}
ch.close();
});
// Consumer
spawn(async () => {
for await (const value of ch) {
console.log('Received:', value);
}
});
Select Statement
import { spawn, Channel, select, selectCase, sleep } from 'pulselang/runtime';
const dataCh = new Channel(1);
const timeoutCh = new Channel(1);
// Slow data source
spawn(async () => {
await sleep(2000);
await dataCh.send('data');
});
// Timeout after 1 second
spawn(async () => {
await sleep(1000);
await timeoutCh.send('timeout');
});
// Wait for first ready channel
const result = await select([
selectCase({
channel: dataCh,
op: 'recv',
handler: (data) => ({ ok: true, data })
}),
selectCase({
channel: timeoutCh,
op: 'recv',
handler: () => ({ ok: false, error: 'Timeout' })
})
]);
console.log(result); // { ok: false, error: 'Timeout' }
Core Features
Structured Concurrency
Tasks form a tree structure with automatic cleanup:
import { spawn, sleep, CancelledError } from 'pulselang/runtime';
const parent = spawn(async () => {
const child = spawn(async () => {
try {
await sleep(5000);
} catch (error) {
if (error instanceof CancelledError) {
console.log('Child was cancelled');
}
}
});
await sleep(100);
return 'parent done';
});
// When parent completes, child is automatically cancelled
await parent.promise;
Graceful Shutdown
import { createServerWithScheduler, setupGracefulShutdown } from 'pulselang/runtime';
const server = createServerWithScheduler(handler, options);
setupGracefulShutdown(server, {
timeout: 30000,
onShutdown: (signal) => {
console.log(`Received ${signal}, shutting down...`);
},
onComplete: (result) => {
console.log(`Shutdown complete: ${result.activeWaitedFor} requests finished`);
}
});
server.listen(3000);
// On SIGTERM or SIGINT:
// 1. Stop accepting new requests
// 2. Wait for active requests (up to timeout)
// 3. Close server
// 4. Exit process
Observability
import { createServerWithScheduler } from 'pulselang/runtime';
import {
enableMetrics,
getMetricsRegistry,
exportPrometheus
} from 'pulselang/runtime/observability';
// Enable metrics collection
enableMetrics();
const server = createServerWithScheduler(async (req, res) => {
if (req.url === '/metrics') {
const metrics = exportPrometheus(getMetricsRegistry());
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(metrics);
return;
}
// Your handler...
res.writeHead(200);
res.end('OK');
});
server.listen(3000);
// GET /metrics returns Prometheus-format metrics:
// pulse_task_spawn_total 42
// pulse_http_request_duration_ms_bucket{le="100"} 35
// pulse_http_request_duration_ms_bucket{le="500"} 40
// ...
Resource Management
import { withResourceManagement } from 'pulselang/runtime/http-integration.js';
import {
AdmissionController,
LoadShedder
} from 'pulselang/runtime/resources';
// Setup resource management
const admissionController = new AdmissionController({
maxConcurrent: 1000,
maxQueued: 5000
});
const loadShedder = new LoadShedder({
enabled: true,
queueDepth: 1000, // Shed load if queue > 1000
memoryThreshold: 0.85 // Shed load if heap > 85%
});
// Wrap handler with resource management
const handler = withResourceManagement(async (req, res) => {
// Your handler code
res.writeHead(200);
res.end('OK');
}, {
admissionController,
loadShedder
});
const server = http.createServer(handler);
s
