Skip to content

materials-commons/feather

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

556 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The Feather Programming Language

This repository holds Feather: a minimal, clean implementation of the TCL core language, suitable for embedding into modern applications.

Runs everywhere

Go logo
Go
Native integration with Go applications.
Full access to the host runtime.
WebAssembly logo JavaScript logo
JavaScript / WebAssembly
Run in any browser or Node.js.
See js/ for the WASM host.

Feather stays mostly faithful to the original, but adds new functionality where user ergonomics count, such as exposing objects from the host to Feather programs.

Omissions from Tcl 9:

  • I/O functions,
  • an event loop,
  • an OO system.

Installation

go get github.com/feather-lang/feather

Feather in your program

Go is the only supported host language at the moment.

See ./cmd/feather-httpd/main.go for an example:

// feather-httpd is an example HTTP server configurable via the feather TCL interpreter.
//
// Usage:
//
// feather-httpd [script.tcl]
//
// If a script is provided, it is evaluated at startup. Then, a REPL is started
// for interactive configuration. The server can be controlled via TCL commands:
//
// route GET /path {script}   - register a route handler
// listen 8080                - start the HTTP server on a port
// stop                       - stop the HTTP server
// response body              - set response body (in handler context)
// status code                - set HTTP status code (in handler context)
// header name value          - set response header (in handler context)
// request method             - get request method (in handler context)
// request path               - get request path (in handler context)
// request header name        - get request header (in handler context)
// request query name         - get query parameter (in handler context)
//
// Example session:
//
// % route GET / {response "Hello, World!"}
// % route GET /time {response [clock format [clock seconds]]}
// % listen 8080
// Listening on :8080
// % stop
// Server stopped

Feather vs Lua

Lua is great for programming extensions to software in the large.

Feather is filling the niche where you have an existing program, and want to add an interactive console or a networked REPL for poking and prodding the program state:

  • giving agents access to your program (like the Chrome Dev Tools, but for YOUR application),
  • configuring an HTTP server while it's running
  • Quake-style consoles,
  • as a configuration file format,
  • allowing users to customize software after you shipped it.

Using the example

Since Feather is designed to be embedded into other programming languages, you need a host for running feather.

The default host for feather, used for developing feather, is written in Go:

Caution

The feather-tester interpreter provided here is only for Feather's internal use and will change frequently -- only use this for playing around.

# build the example interpreter in bin/feather-tester
mise build

# start the repl
mise exec -- feather-tester

In the REPL:

% set greeting "Hello, World!"
Hello, World!
% string length $greeting
13

% proc greet {name} {
    return "Hello, $name!"
}
% greet TCL
Hello, TCL!

% set numbers {1 2 3 4 5}
1 2 3 4 5
% lindex $numbers 2
3
% llength $numbers
5

% foreach n $numbers {
    if {$n > 3} { break }
    echo $n
}
1
2
3

% expr {2 + 2 * 3}
8
% set x 10
10
% incr x 5
15

% dict set config host localhost
host localhost
% dict set config port 8080
host localhost port 8080
% dict get $config port
8080
Run the test harness
$ mise test
[build:harness] $ cd harness
[build:core] $ mkdir -p build
[build:harness] Finished in 207.2ms
[build:core] Finished in 800.3ms
[build:feather-tester] $ go build -o $MISE_CONFIG_ROOT/bin/feather-tester ./cmd/feather-tester
[build:feather-tester] Finished in 503.8ms
[test] $ harness run --host bin/feather-tester testcases/
[test]
[test] 1024 tests, 1024 passed, 0 failed
[test] Finished in 9.88s
Finished in 11.19s

Philosophy

TCL was conceived at a time when most networked software was written in C at the core, the internet was young, user expectations were looser.

It is a tiny language full of great ideas, but features that were useful 20 years ago are a hindrance today:

  • I/O in the language is an obstacle, as the host is more than likely to already have taken a stance on how it wants to handle I/O,
  • a built-in event loop for multiplexing I/O and orchestrating timers was useful when no host could easily provide this, but event loops are widespread and having to integrate multiple event loops in one application is error-prone.
  • reference counting with lots of calls to malloc and free works great for standalone TCL, but the emergence of zig and wasm incentivizes being in control of allocations.

So what ideas are worth preserving?

A pure form of metaprogramming, syntax moldable like clay, with meaning to be added at a time and in a form that is convenient for that particular use case.

A transparent execution environment: every aspect of a running TCL program can be inspected from within that program, and often even modified.

A focus on expressing computation in the form of instructions to carry out.

The latter point is key: agentic coding benefits from an inspectable and moldable environment. Having the agent talk to your running program gives it highly valuable feedback for a small amount of tokens.

The browser is one example of this model being successful, but what about all the other applications? Your job runner, web server, database, your desktop or mobile app.

feather wants to be the thin glue layer that's easy to embed into your programs, so that you can talk to them while they are running.

Another way to look at TCL is this: it is a Lisp-2 with fexprs that extend to the lexical syntax level. Maybe that is more exciting.

Here you will find a faithful implementation of:

  • control flow and execution primitives: proc, foreach, for, while, if, return, break, continue, error, tailcall, try, throw, catch, switch
  • introspection capabilities: info, errorCode, errorInfo, trace
  • values and expressions: expr, incr, set, unset, global, variable
  • metaprogramming: upvar, uplevel, rename, unknown, namespace
  • data structures: list, dict, string, apply
  • string manipulation: split, subst, concat, append, regexp, regsub, join

Notable omissions (all to be covered by the host):

  • I/O: chan, puts, gets, refchan, transchan, after, vwait, update These are better provided by the host in the form of exposed commands.

  • OO: feather intended use case is short, interactive programs similar to bash. Programming in the large is explicitly not supported.

  • Coroutines: feather interpreter objects are small and lightweight so you can have of them if you need something like coroutines.

Notables qualities of the implementation:

This implementation is pure: it does not directly perform I/O or allocation or interact with the kernel at all. It only provides TCL parsing and semantics.

All memory is allocated, accessed, and released by the embedding host. The embedding host is highly likely to already have all the building blocks we care about in the implementation and there is little value in building our own version of regular expressions, lists, dictionaries, etc.

While this requires the host to implement a large number of functions, the implementation is largely mechanical, which makes it a prime candidate for delegating to agentic coding tools.

About

The core implementation of Feather

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 50.8%
  • HTML 32.7%
  • Go 12.3%
  • JavaScript 3.8%
  • Tcl 0.2%
  • Shell 0.1%
  • Makefile 0.1%