LIPI — LOADING ENGINE...
Stable Release · v3.0 · AST Compiler

Write logic.
Control the web.

LIPI is a compiled, web-native programming language. Python's readability. JavaScript's reach. Zero configuration. Runs entirely in the browser.

main.lipi
Code
# Memory Reinforcement Simulation
let memory = {alpha: 0, beta: 0, gamma: 0}
let keys   = ["alpha", "beta", "gamma"]

func reinforce(key) {
  memory[key] += 14
  if memory[key] > 100 { memory[key] = 100 }
  let bar = $("#mem-" + key)
  let lbl = $("#lbl-" + key)
  if bar != null {
    bar.style.width = memory[key] + "%"
    lbl.innerText   = memory[key] + "%"
  }
}

func runSim() {
  for round in range(6) {
    for k in keys {
      reinforce(k)
      wait(120)
    }
  }
}

runSim()
Live Output
Ready
Memory Reinforcement System
alpha 0%
beta 0%
gamma 0%
// Click Run to execute simulation
AST
Compiler Architecture
30+
Built-in Functions
0ms
Setup Time
100%
Browser Native
The Language

JavaScript was built for browsers.
LIPI was built for thinking.

JavaScript is powerful but verbose. Python is clean but runs on servers. LIPI takes the best of both — Python's readable syntax and JavaScript's direct browser access — and compiles transparently to JavaScript at runtime.

It was designed for one thing: writing logic that interacts with a web page, without fighting the language to do it. No async/await ceremony. No event listener boilerplate. No DOM query soup. Just clean, readable code that does what you mean.

Philosophy #1 — Syntax should disappear

When you're designing an algorithm or building a visual simulation, the language should get out of the way. LIPI has no semicolons, no type annotations, no boilerplate.

Philosophy #2 — The DOM is a first-class citizen

HTML element selection and event binding are language primitives in LIPI, not library calls. #box selects an element. on btn.click binds an event. Nothing to import.

Philosophy #3 — Async should be invisible

Every function in LIPI is internally async. wait(500) pauses execution for 500ms — code after it runs after the pause. No callbacks, no promises, no async/await in your code.

Where LIPI excels

Algorithm Visualization

Write bubble sort, BFS, or a memory allocator and watch it animate on screen using DOM updates and wait(). The code reads like a textbook algorithm.

Interactive Simulations

Build state machines, progress systems, or real-time dashboards. LIPI's async model lets you build timed simulations that update the page step-by-step without any framework.

Teaching Programming

LIPI's syntax is intentionally close to pseudocode. Students learning data structures can write their first algorithm in LIPI with the same mental model they'd use on paper.

Rapid UI Prototyping

Design in the HTML tab. Write behavior in the LIPI tab. No build step. No bundler. Instant preview. The Studio gives you a full-stack environment in the browser.

Under the Hood

The LIPI Compiler Pipeline

LIPI is not an interpreter walking an AST node-by-node. It is a compiler that transforms your source code into valid JavaScript, then executes it. This makes it fast and predictable.

Step 1
Lexer

Your source text is scanned character-by-character into typed tokens: keywords, identifiers, strings, numbers, operators. Invalid characters produce a LexError immediately.

INPUT: let x = 10 + 5
TOKENS: Keyword Ident Assign Number Plus Number
Step 2
Parser (Pratt)

A Recursive Descent parser with a Pratt (top-down operator precedence) expression engine builds a typed AST. Incorrect syntax causes a ParseError with a line number.

AST NODE:
VarDecl { name: "x",
  init: BinaryExpr(+, 10, 5) }
Step 3
Code Generator

The AST is walked and each node emits JavaScript. All code is wrapped in an async IIFE. User functions are tracked so call sites are automatically awaited.

OUTPUT JS:
let x = (10 + 5);
Step 4
JS Runtime

The compiled JavaScript is executed via new Function() in the page scope. All browser globals are accessible. Errors are caught and displayed with full context.

RESULT:
// x = 15 in scope
// DOM fully accessible

Why you never write await

When LIPI compiles wait(500), it emits await __wait(500) in JavaScript. The surrounding async IIFE pauses at this line for 500ms, then continues — exactly like blocking I/O in Python.

Every function you declare with func is compiled as async function. The compiler tracks all user-declared function names, and every call site to a user function automatically receives await in the generated code.

// LIPI source
func process() {
  wait(1000)
  log("done")
}
process()
// Compiled JS
async function process() {"{
  await __wait(1000);
  console.log('done');
}"}
(await process());

Error handling built-in

LIPI has three distinct error types, each thrown at a specific phase. Errors include line numbers and context — you'll never see a cryptic JavaScript stack trace.

LexError
Unknown character in source code. Line number included.
ParseError
Invalid syntax — wrong token, missing brace, bad expression.
Runtime Error
Logic error during execution — null access, type mismatch, assertion failure.
Language Features

Everything you need.
Nothing you don't.

A complete language core: variables, loops, functions, objects, async, DOM, events — all with clean, unambiguous syntax.

Variables & Types
let name = "Alice" # string let score = 98.5 # number let active = true # boolean let msg = `Hi {name}!` # template

Dynamic typing. Five primitives: string, number, boolean, null, undefined. Template literals with {expr} interpolation.

Control Flow
if score > 90 { log("Excellent") } else if score > 70 { log("Good") } else { log("Needs work") }

Full if / else if / else. Conditions don't need parentheses. Ternary: "yes" if x else "no".

Loops
# Arrays: iterate values for item in ["a","b","c"] { ... } # Objects: iterate keys for key in {x:1,y:2} { ... } # Numbers: 0..n-1 for i in 5 { ... }

Smart for...in iteration over arrays, objects, numbers. while loops. break and continue supported.

Functions
func fib(n) { if n <= 1 { return n } return fib(n-1) + fib(n-2) } log(fib(10)) # 55

Recursive functions work out of the box. All func declarations are internally async — they can freely call wait().

Objects & Arrays
let user = {name:"Bob", age:25} log(user.name) # dot user["score"] = 99 # bracket delete user.age # delete for k in user { ... } # keys

Full object and array support with dot/bracket access, mutation, deletion, and key iteration.

Async & DOM Events
let btn = #my-button on btn.click { btn.style.bg = "#7c3aed" wait(500) btn.innerText = "Done ✓" }

DOM selection with #id or $(selector). Event binding with on. wait() pauses execution transparently.

Full Operator Set
+ - * / %Arithmetic
**Exponentiation (2**8 = 256)
//Floor division (10//3 = 3)
== != < > <= >=Comparison (strict equality)
and or notLogical (Python-style)
+= -= *= //= **=Compound assignment
++ --Prefix / postfix increment
val if cond else otherPython-style ternary
30+ Built-in Functions
len(x)
range(a,b,step)
keys(obj)
values(obj)
has(obj,key)
str int float bool
abs floor ceil
round(n,dp)
max min sqrt
random(a,b)
append pop
sort reverse
filter map find
join split
sum avg
upper lower trim
toJSON fromJSON
merge copy
show hide clear
addClass setText
Interactive Playground

Real code. Real output.

These are live LIPI programs running in your browser right now. Edit the code and click Run to see changes instantly.

DOM Event Handler
Preview →
Async Countdown
Output →
// Click Run
Algorithm — Bubble Sort
Output →
// Click Run
State Machine
// Click Run
Flagship Demo

Build real systems.
Not toy examples.

This demo implements a memory reinforcement algorithm — the same conceptual model used in spaced-repetition learning systems like Anki. Written in ~20 lines of LIPI, it dynamically updates progress bars in real-time.

Each memory slot has a strength score that increases when reinforced and decays over time. The visual bars update live as the algorithm runs. This is exactly the kind of simulation LIPI was built for.

All DOM updates driven by LIPI — no JavaScript written
wait() creates the step-by-step visual progression
Object mutation and has() used for state management
Runs entirely in browser — zero dependencies
memory_system.lipi
Idle
Concept Alpha0 / 100
Concept Beta0 / 100
Concept Gamma0 / 100
Concept Delta0 / 100
Concept Epsilon0 / 100
Overall Retention 0%
LIPI Source
let slots = {alpha:0, beta:0, gamma:0, delta:0, epsilon:0}

func reinforce(key) {
  slots[key] += random(8, 22)
  if slots[key] > 100 { slots[key] = 100 }
  updateBar(key, slots[key])
}

for round in range(8) {
  for k in slots { reinforce(k); wait(80) }
}
Language Comparison

How LIPI compares

Not a replacement for Python or JavaScript. A focused tool for browser-based logic and visual systems.

Feature LIPI JavaScript Python
Setup required✦ None± Build tools optional✕ Runtime required
Clean, minimal syntax✦ Yes✕ Verbose✦ Yes
DOM manipulation built-in✦ Language primitive± Library required✕ Not applicable
Async without async/await✦ Transparent✕ Explicit required✕ Explicit required
Runs in the browser✦ Native✦ Native✕ Needs Pyodide/WASM
Event binding syntaxon el.click✕ addEventListener()✕ Not applicable
Visual animation (wait)wait(ms)✕ setTimeout/Promise✕ time.sleep (blocks)
For-in over objects✦ Iterates keys± for...in (quirky)✦ dict iteration
Style shortcutsel.style.bg✕ Full property names✕ Not applicable
Compiled (not interpreted)✦ AST → JS✦ V8 JIT± Bytecode
Learning curve✦ Low (pseudocode-like)✕ High (async, this, etc.)✦ Low
✦ = strong advantage    ± = partial/conditional    ✕ = limitation or not applicable
Quick Reference

Syntax at a glance

The complete LIPI syntax in one scroll. For the full manual, see the documentation.

Variables
let x = 42
let s = "hello"
let b = true
x += 10
x++
Conditions
if x > 10 {
  log("big")
} else {
  log("small")
}
Loops
for i in range(5) { ... }
for x in [1,2,3] { ... }
for k in obj { ... }
while x > 0 { x-- }
Functions
func add(a, b) {
  return a + b
}
let r = add(3, 4)  # 7
Objects
let o = {a: 1, b: "hi"}
log(o.a)
o["c"] = true
delete o.b
log(has(o, "c"))
Arrays
let a = [1, 2, 3]
append(a, 4)
log(len(a))   # 4
log(sum(a))   # 10
log(sort(a))
DOM Selection
# By ID (shorthand)
let el = #my-box
# By CSS selector
let el = $("#my-box")
# Multiple elements
let els = queryAll(".card")
Events & Async
on btn.click {
  wait(500)
  el.innerText = "Done"
}
# sleep = alias for wait
sleep(1000)
Expressions
2 ** 8        # 256
10 // 3       # 3 (floor)
`Hi {name}!`  # interpolation
"y" if x else "n" # ternary
Developer Experience

Zero to running in seconds.

No terminal. No npm install. No webpack config. Open the Studio and start writing.

Instant Iteration

Press Ctrl+Enter to run. Preview resets and re-executes in under 50ms. No build step, no hot reload delay.

Cloud Auto-Save

Projects sync to Firestore in real-time with a 1.5s debounce. Your code is safe even if you close the tab. Offline support included.

Full Stack Editor

Two tabs: main.lipi for logic, index.html for layout. A live preview and console sit side by side. Split panes, resizable.

LIPI Studio — Full Stack
Saved
# main.lipi
log("🚀 App Starting...")

let box     = #demo-box
let counter = 0

on box.click {
  counter += 1
  box.innerText = "Clicks: " + counter
  box.style.bg = "hsl(" +
    (counter * 30) + ",70%,45%)"
}
Live Preview
Click Me
Logic is in the Lipi tab →
› 🚀 App Starting...
Best Practices

Write LIPI that works.

Four patterns that separate reliable code from fragile code.

Always guard DOM selectors
let el = #my-box if el != null { el.innerText = "Safe" }

If the element doesn't exist in the HTML tab, the selector returns null. Accessing .style or .innerText on null throws a runtime error.

Convert input before arithmetic
let raw = getInput("Number:") let n = int(raw) log(n * 2) # correct

getInput() always returns a string. Adding a string to a number concatenates instead of adding. Always use int() or float() first.

Declare functions before calling them
# ✓ Define first func greet(name) { log(name) } # ✓ Then call greet("Alice")

LIPI functions are not hoisted at the top level. Declare a function before the line that calls it in the main script flow.

Use has() before accessing object keys
let cache = {} if has(cache, key) { return cache[key] }

Accessing a key that doesn't exist on an object returns undefined, which can cause downstream bugs. Use has() to check first.

FAQ

Common questions

What is LIPI and who is it for?

LIPI is a compiled, web-native programming language designed for writing algorithms, building interactive browser applications, and teaching programming concepts. It is aimed at developers who want Python's clean syntax combined with direct browser access — without learning JavaScript's complexity.

Does LIPI compile to JavaScript?

Yes. LIPI is a proper compiler — it runs a Lexer, Parser, AST builder, and Code Generator entirely in the browser. Your LIPI source code is transformed into valid JavaScript at runtime, which is then executed via new Function(). The generated JavaScript is readable and can be inspected if a syntax error occurs.

Why don't I need to write async/await?

The LIPI code generator wraps all compiled code in an async IIFE (Immediately Invoked Function Expression). Every call to wait() compiles to await __wait(). Every user-declared function is compiled as async function, and every call to a user function receives await at the call site. You write synchronous-looking code; the compiler handles the async plumbing.

Can LIPI access JavaScript libraries?

Since LIPI compiles to JavaScript and runs in the browser scope, all global variables are accessible — including Math, JSON, Object, Array, Date, and any library loaded on the page. You can call Math.random() or JSON.stringify() directly in LIPI code.

Do I need to install anything?

No. LIPI Studio runs entirely in the browser with no installation, no Node.js, no npm, and no build tools. Open the Studio, sign in, and start writing. Your projects are saved to the cloud automatically.

Is LIPI suitable for production web apps?

LIPI is optimized for interactive demos, algorithm visualization, simulations, and educational tooling. For production applications requiring complex state management, server interaction, or a large codebase, JavaScript or TypeScript with a framework remains the better choice. LIPI excels at the intersection of "I want to write an algorithm and see it run visually in the browser."

Built by developers,
for developers.

Get Started

Start writing
real algorithms today.

LIPI Studio is free, browser-based, and ready in seconds. No account needed to explore the docs and demos.