Skip to content

A simple concatenative programming language written in Go (for fun). WIP.

License

Notifications You must be signed in to change notification settings

brendantang/naiveconcat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

98 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

naiveconcat

A simple concatenative programming language written in Go. WIP.

Draws inspiration from Factor, Forth, Scheme. I leaned a lot on Rob Pike's talk about building a lexer.

Overview

There is a stack, which is a first-in-last-out pile of values. Values like numbers and strings get pushed on top of the stack:

> 1 2 3
[1 2 3]

> "foo" 
[1 2 3 "foo"]

> 100 -- a `--` starts a comment, input is ignored until end of line
[1 2 3 "foo" 100]

A procedure is a value that manipulates the stack (and the dictionary), and may perform side effects like printing output. Here are examples of procedures for addition, multiplication, and printing output.

> 3 3 +
[6]

> 2
[6 2]

> *
[12]

> say -- pop the top value and print it
12
[]

The dictionary binds words to definitions. A word is a value that defines another value. To evaluate a word, substitute it for its definition and evaluate that.

> 100 "a-cool-number" 
[100 "a-cool-number"]

> let
[]

> a-cool-number
[100]

The word let pops a string and another value, and adds a word to the dictionary using the string as the word's name and the other value as its definition.

A quotation is a value which contains other values. Evaluating a quotation just pushes it on the stack, which makes it useful to "wrap" words and procedures that you aren't ready to evaluate yet.

> 2 3 {+}  -- the word `+` is wrapped in a quotation
[2 3 {+}]

> apply  -- the word `apply` 'unwraps' a quotation
[5]

> {1 +}  -- you can wrap more than one value in a quotation
[5 {1 +}]

> apply
[6]

> {1 +} "increment" let  -- save {1 +} as the definition for the word `increment`
[6]

> increment  -- evaluating `increment` pushes the quotation on the stack
[6 {1 +}]

> apply  -- it still needs to be applied
[7]

Words like +, *, and say are defined by primitive procedures built into the language. But you can also create your own procedures using the word lambda. Lambda pops the top value off the stack and pushes a procedure that will apply that value.

> { "I'm a procedure!" say } lambda
[proc:{0x10c1ae0}]

> apply  -- you can apply a procedure on the stack
"I'm a procedure!"
[]

> { 1 + } lambda "increment-proc" let  -- but it's more useful to save it as a word
[]

> 1 increment-proc  -- evaluating a word with a procedure definition applies that procedure
[2]

Making a procedure and then saving it as a word definition is pretty important, so there is a keyword for it: define.

> {2 *} "double" define
[]

> 100 double
[200]

About

A simple concatenative programming language written in Go (for fun). WIP.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published