JSPM

rip-lang

2.8.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 204
  • Score
    100M100P100Q97086F
  • License MIT

A modern language that compiles to JavaScript

Package Exports

  • rip-lang
  • rip-lang/loader

Readme

Rip Logo

Rip

A modern language that compiles to JavaScript

Version Dependencies Tests License


Rip is a modern language inspired by CoffeeScript. It compiles to ES2022 (classes, ?., ??, modules), adds about a dozen new operators, includes built-in reactivity, and sports a self-hosting compiler with zero dependencies — all in about 10,000 lines of code.

No imports. No hooks. No dependency arrays. Just write code.

data = fetchUsers!                  # Dammit operator (call + await)
user = User.new name: "Alice"       # Ruby-style constructor
squares = (x * x for x in [1..10])  # List comprehension

str =~ /Hello, (\w+)/               # Regex match
log "Found: #{_[1]}"                # Captures in _[1], _[2], etc.

What makes Rip different:

  • Modern output — ES2022 with native classes, ?., ??, modules
  • New operators!, !?, //, %%, =~, .new(), and more
  • Reactive operators:=, ~=, ~> as language syntax
  • Zero dependencies — everything included, even the parser generator
  • Self-hostingbun run parser rebuilds the compiler from source

Installation

bun add -g rip-lang            # Install globally
rip                            # Interactive REPL
rip file.rip                   # Run a file
rip -c file.rip                # Compile to JavaScript

Language

Functions & Classes

def greet(name)                # Named function
  "Hello, #{name}!"

add = (a, b) -> a + b          # Arrow function
handler = (e) => @process e    # Fat arrow (preserves this)

class Dog extends Animal
  speak: -> log "#{@name} barks"

dog = Dog.new("Buddy")         # Ruby-style constructor

Destructuring & Comprehensions

{name, age} = person
[first, ...rest] = items

squares = (x * x for x in [1..10])   # Array comprehension
console.log x for x in items         # Loop (no array)

Async & Chaining

def loadUser(id)
  response = await fetch "/api/#{id}"
  await response.json()

user?.profile?.name            # Optional chaining
data = fetchData!              # Await shorthand

Reactivity

State, computed values, and effects as language operators:

Operator Mnemonic Example What it does
= "gets value" x = 5 Regular assignment
:= "has state" count := 0 Reactive state container
~= "always equals" twice ~= count * 2 Auto-updates on changes
~> "reacts to" ~> log count Runs on dependency changes
=! "equals, dammit!" MAX =! 100 Readonly constant

New Operators

Operator Example What it does
! (dammit) fetchData! Calls AND awaits
! (void) def process! Suppresses implicit return
!? (otherwise) val !? 5 Default only if undefined
?: (ternary) x > 0 ? 'yes' : 'no' JS-style ternary expression
?. ?[] a?.b a?[0] Optional chaining (both styles)
... (spread) [...rest, last] Spread at start or end (JS: end only)
// 7 // 2 Floor division → 3
%% -1 %% 3 True modulo → 2
=~ str =~ /Hello, (\w+)/ Match (captures in _)
[//, n] str[/Hello, (\w+)/, 1] Extract capture n
.new() Dog.new() Ruby-style constructor

Optional chaining — Both CoffeeScript and ES6 styles are supported:

Syntax Style Compiles to
obj?[0] CoffeeScript (obj != null ? obj[0] : undefined)
fn?(arg) CoffeeScript (typeof fn === 'function' ? fn(arg) : undefined)
obj?.[0] ES6/JS obj?.[0]
fn?.(arg) ES6/JS fn?.(arg)

Heredoc & Heregex

Heredoc — The closing ''' position sets the left margin (smart dedent):

html = '''
    <div>
      <p>Hello</p>
    </div>
  '''
# Result: "  <div>\n    <p>Hello</p>\n  </div>" (note the leading 2 spaces)

Heregex — Extended regex with comments and whitespace:

pattern = ///
  ^(\d{3})    # area code
  -(\d{4})    # number
///

vs React / Vue / Solid

Concept React Vue Solid Rip
State useState() ref() createSignal() x := 0
Computed useMemo() computed() createMemo() x ~= y * 2
Effect useEffect() watch() createEffect() ~> body

Rip's reactivity is framework-agnostic — use it with React, Vue, Svelte, or vanilla JS.


vs CoffeeScript

Feature CoffeeScript Rip
Output ES5 (var, prototypes) ES2022 (classes, ?., ??)
Reactivity None Built-in
Dependencies Multiple Zero
Self-hosting No Yes
Lexer 3,558 LOC 3,250 LOC
Compiler 10,346 LOC 5,878 LOC
Total 17,760 LOC ~10,100 LOC

Smaller codebase, modern output, built-in reactivity.


Browser

Run Rip directly in the browser (51KB compressed):

<script src="https://shreeve.github.io/rip-lang/docs/dist/rip.browser.min.js"></script>
<script type="text/rip">
  def greet(name)
    console.log "Hello, #{name}!"
  greet "World"
</script>

Try it live: shreeve.github.io/rip-lang


Architecture

Source → Lexer → Parser → S-Expressions → Codegen → JavaScript
                          ["=", "x", 42]

Simple arrays instead of AST node classes. The compiler is self-hosting — bun run parser rebuilds from source.


The Rip Stack

Rip includes optional packages for full-stack development:

Package Purpose Lines
@rip-lang/api Web framework (Sinatra-style) ~595
@rip-lang/server Multi-worker process manager ~1,110
@rip-lang/db DuckDB HTTP server ~225
@rip-lang/schema ORM with reactive models ~420
bun add @rip-lang/api @rip-lang/server

Full stack documentation →


Implicit Commas

Rip rescues what would be invalid syntax and gives it elegant meaning. When a literal value is followed directly by an arrow function, Rip inserts the comma for you:

# Clean route handlers (no comma needed!)
get '/users' -> User.all!
get '/users/:id' -> User.find params.id
post '/users' -> User.create body

# Works with all literal types
handle 404 -> { error: 'Not found' }
match /^\/api/ -> { version: 'v1' }
check true -> enable()

This works because '/users' -> was previously a syntax error — there's no valid interpretation. Rip detects this pattern and transforms it into '/users', ->, giving dead syntax a beautiful new life.

Supported literals: strings, numbers, regex, booleans, null, undefined, arrays, objects


Quick Reference

rip                    # REPL
rip file.rip           # Run
rip -c file.rip        # Compile
rip -t file.rip        # Tokens
rip -s file.rip        # S-expressions
bun run test           # 1021 tests
bun run parser         # Rebuild parser
bun run browser        # Build browser bundle

Documentation

Guide Description
docs/GUIDE.md Language guide
docs/REACTIVITY.md Reactivity deep dive
docs/INTERNALS.md Compiler architecture
packages/ Full-stack packages
CONTRIBUTING.md How to contribute

Zero Dependencies

{ "dependencies": {} }

Everything included: compiler, parser generator, REPL, browser bundle, test framework.


Philosophy

Simplicity scales.

Simple IR (S-expressions), clear pipeline (lex → parse → generate), minimal code, comprehensive tests.


Inspired by: CoffeeScript, Lisp, Ruby | Powered by: Bun

MIT License

Start simple. Build incrementally. Ship elegantly.