⛳ A minimal programming language inspired by Ink, JavaScript, and Python.

Overview

Go

Golfcart

My blog post: Creating the Golfcart Programming Language


Golfcart is a minimal programming language inspired by Ink, JavaScript, and Python – implemented in Go. It's a toy programming language that I built to use for Advent of Code 2021. Another motivation was to learn how to write an interpreter from scratch.

// Here's the classic interview question FizzBuzz
for i = 1; i < 101; i = i + 1 {
    log(if i % 3 == 0 and i % 5 == 0 {
       "FizzBuzz"
    } else if i % 3 == 0 {
       "Fizz"
    } else if i % 5 == 0 {
       "Buzz"
    } else {
       str(i)
    })
}

Golfcart is a dynamic strongly typed language with support for bools, strings, numbers (float64), lists, dicts, and nil (null). There is full support for closures and functions can alter any variable in a higher scope.

counter = () => {
    n = 0
    () => {
        n = n + 1
        n
    }
}

my_counter = counter()
my_counter() // 1

assert(my_counter(), 2)

For Golfcart, I began with a desire to design a small programming language that didn't use semi-colons or automatic semicolon insertion. So, no statements, and everything should be an expression that evaluates to a value. For example:

  • if/else if/else evaluates to the successful branch
  • A variable declaration evaluates to the value
  • Setting a dict value evaluates to the value
  • A for loop evaluates to the number of times the condition expression succeeded
assert(
    // This runs five times
    for i = 0; i < 5; i = i + 1 {}, 5
)

Getting Started

A Golfcart program is a series of expressions. Line breaks are optional and there are no semi-colons. The final expression is sent to stdout.

a = 1 b = 2 assert(a + b, 3) // A successful assert() evaluates to nil

There are seven types. A type-check can be performed with type().

// Bools
true or false
true and true

// Numbers
1
1.1 + 1.1 // 2.2

// Strings
"multi-line
string"
"1" + "2" // "12"

// Lists
[1, 2]
nums = [3, 4]
nums.append(5) // [3, 4, 5]
[0] + [1] // [0, 1]

// Dicts
{a: 1} // Accessed by `.a` or `["a"]` like JavaScript
{b: n => n + 1} // Values can be any type
keys({a: 1}) // ["a"]

// Functions
_ => nil // All user-defined functions are anonymous, assignable by variable
n => n + 1
sum = (x, y) => x + y

// Nil
nil
nil == nil // true

The Fibonacci sequence.

// Naive
t = time()
fib = n => if n == 0 {
    0
} else if n == 1 {
    1
} else {
    fib(n - 1) + fib(n - 2)
}
fib(20)
log("fib: " + str(time() - t))

// With memoization 
t = time()
cache = {"0": 0, "1": 1}
fib_memo = n => if cache[n] != nil {
    cache[n]
} else {
    cache[n] = fib_memo(n - 1) + fib_memo(n - 2)
}
fib_memo(20)
log("fib_memo: " + str(time() - t))

For more detailed examples, see:

(All the above are used as part of Golfcart's test suite)

Scope Rules

Let's talk about stack frames in Golfcart. A stack frame is a map of variables in scope. It's a recursive structure, every stack frame has a parent apart from the global frame. All functions are anonymous and create closures. Any variable referenced in a higher scope can be altered. Examples explain this better than words.

a = 1
a_function = () => a = 2 // Closure created
a_function() // When called, `a` is changed
a // 2

if true {
    // `b` is not defined in a higher scope
    // So, `b` is declared only within this scope
    b = 3
}
b // Error: cannot find value for key 'b'

c = nil
if true {
    // This assignment recursively looks in higher scopes for `c`
    // it's found and that value is altered
    c = 4
}
c // 4

Usage

Pass a Golfcart program as the first command-line argument

$ ./golfcart-linux program.golf

Run the binary with no command-line arguments to open the REPL.

$ ./golfcart-linux 

      .-::":-.
    .'''..''..'.
   /..''..''..''\
  ;'..''..''..''.;
  ;'..''..''..'..;
   \..''..''..''/
    '.''..''...'
      '-..::-' Golfcart v0.1
λ 

Use -ebnf to print the Extended Backus–Naur form grammar to stdout and quit.

Use -version to print the version to stdout and quit.

Building and tests

Create releases.

./build.sh

Run all tests (they also run via GitHub Action on commit).

go test ./...

Contributions

More than welcome! Raise an issue with a bug report/feature proposal and let's chat.

License

MIT.

Releases(v0.1)
  • v0.1(Jul 14, 2021)

    This is the initial release of Golfcart! My toy programming language is feature complete.

    The language syntax is fully implemented and complex programs can be run.

    e.g. the Fibonacci sequence.

    // Naive
    t = time()
    fib = n => if n == 0 {
        0
    } else if n == 1 {
        1
    } else {
        fib(n - 1) + fib(n - 2)
    }
    fib(20)
    log("fib: " + str(time() - t))
    
    // With memoization 
    t = time()
    cache = {"0": 0, "1": 1}
    fib_memo = n => if cache[n] != nil {
        cache[n]
    } else {
        cache[n] = fib_memo(n - 1) + fib_memo(n - 2)
    }
    fib_memo(20)
    log("fib_memo: " + str(time() - t))
    

    The test suite + example programs all run without error. But you shouldn't use this in production.

    Source code(tar.gz)
    Source code(zip)
    golfcart-darwin(3.18 MB)
    golfcart-linux(3.20 MB)
    golfcart-windows(3.29 MB)
Owner
Andrew Healey
Software engineer / writer
Andrew Healey
A JavaScript interpreter in Go (golang)

otto -- import "github.com/robertkrimen/otto" Package otto is a JavaScript parser and interpreter written natively in Go. http://godoc.org/github.com/

Robert Krimen 6.1k Jul 19, 2021
naive go bindings to the CPython C-API

go-python Naive go bindings towards the C-API of CPython-2. this package provides a go package named "python" under which most of the PyXYZ functions

Sebastien Binet 1.3k Jul 19, 2021
Execute JavaScript from Go

Execute JavaScript from Go Usage import "rogchap.com/v8go" Running a script ctx, _ := v8go.NewContext() // creates a new V8 context with a new Isolate

Roger Chapman 1.4k Jul 22, 2021
v8 javascript engine binding for golang

Go-V8 V8 JavaScript engine bindings for Go. Features Thread safe Thorough and careful testing Boolean, Number, String, Object, Array, Regexp, Function

Hoping White 184 Jul 14, 2021
Floppa programming language inspired by the brainf*ck programming language. Created just for fun and you can convert your brainf*ck code to floppa code.

Floppa Programming Language Created just for fun. But if you want to contribute, why not? Floppa p.l. inspired by the brainf*ck programming language.

null 11 Jul 19, 2021
Pineapple Lang is a simple programming language demo implements by Go

Pineapple Lang is a simple programming language demo implements by Go. It includes a hand-written recursive descent parser and a simple interpreter, although the language is not even Turing-complete. But this repo's main goal is to give beginners of compilation principles a warm up and a simple look at how a programming language is built.

karminski-牙医 181 Jul 8, 2021
ECMAScript/JavaScript engine in pure Go

goja ECMAScript 5.1(+) implementation in Go. Goja is an implementation of ECMAScript 5.1 in pure Go with emphasis on standard compliance and performan

Dmitry Panov 2.3k Jul 25, 2021
a dynamically typed, garbage collected, embeddable programming language built with Go

The agora programming language Agora is a dynamically typed, garbage collected, embeddable programming language. It is built with the Go programming l

Martin Angers 324 Jul 21, 2021
Gentee - script programming language for automation. It uses VM and compiler written in Go (Golang).

Gentee script programming language Gentee is a free open source script programming language. The Gentee programming language is designed to create scr

Alexey Krivonogov 78 Jul 18, 2021
A Lisp-dialect written in Go

Lispy ✏️ Intro Lispy is a programming language that is inspired by Scheme and Clojure. It's a simple Lisp-dialect I built to better understand Lisp an

Amir Bolous 12 Jun 11, 2021
The Slick programming language is an s-expression surface syntax for Go.

The Slick programming language The Slick programming language is a Lisp/Scheme-style s-expression surface syntax for the Go programming language, with

null 99 Jul 16, 2021
❄️ Elsa is a minimal, fast and secure runtime for JavaScript and TypeScript written in Go

Elsa Elsa is a minimal, fast and secure runtime for JavaScript and TypeScript written in Go, leveraging the power from QuickJS. Features URL based imp

Elsa 2.4k Jul 26, 2021
Golem is a general purpose, interpreted scripting language.

The Golem Programming Language Golem is a general purpose, interpreted scripting language, that brings together ideas from many other languages, inclu

Mike Jarmy 1.3k Jun 2, 2021
Small Clojure interpreter, linter and formatter.

Joker is a small Clojure interpreter, linter and formatter written in Go. Installation On macOS, the easiest way to install Joker is via Homebrew: bre

Roman Bataev 1.2k Jul 25, 2021