⛳ 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.

You might also like...
Create isolated environments for installing Go packages. Similar to virtualenv for Python.

DEPRECATED: This project is no longer maintained. Goenv Goenv lets you create an isolated environment where you install Go packages, binaries, or even

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

Simple, safe and compiled programming language.

The X Programming Language Simple, safe and compiled programming language. Table of Contents Overview OS Support Contributing License Overview The X p

Monkey programming language project from 'Writing An Interpreter In Go'and 'Writing A Compiler In Go' Books
Monkey programming language project from 'Writing An Interpreter In Go'and 'Writing A Compiler In Go' Books

Monkey Monkey programming language 🐒 project from "Writing An Interpreter In Go

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

Port of the lemon parser generator to the Go programming language

From the golang-nuts mailing list (with few modifications): --== intro ==-- Hi. I just want to announce a simple port of the lemon parser generator

An LL(1) parser generator for the Go programming language.

What is it? I have implemented an LL(1) parser generator for the Go programming language. I did this to build parse trees for my HAML parser. You can

PHP bindings for the Go programming language (Golang)

PHP bindings for Go This package implements support for executing PHP scripts, exporting Go variables for use in PHP contexts, attaching Go method rec

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

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
❄️ 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.7k Jan 7, 2023
T# Programming Language. Something like Porth, Forth but written in Go. Stack-oriented programming language.

The T# Programming Language WARNING! THIS LANGUAGE IS A WORK IN PROGRESS! ANYTHING CAN CHANGE AT ANY MOMENT WITHOUT ANY NOTICE! Something like Forth a

T# 92 Jun 29, 2022
Yayx programming language is begginer friendly programming language.

Yayx Yayx programming language is begginer friendly programming language. What have yayx: Easy syntax Dynamic types Can be compiled to outhers program

null 1 Dec 27, 2021
Yayx programming language is begginer friendly programming language.

Yayx Yayx programming language is begginer friendly programming language. What have yayx: Easy syntax Dynamic types Can be compiled to outhers program

Yayx Programming Language 7 May 20, 2022
Go bindings to QuickJS: a fast, small, and embeddable ES2020 JavaScript interpreter.

quickjs Go bindings to QuickJS: a fast, small, and embeddable ES2020 JavaScript interpreter. These bindings are a WIP and do not match full parity wit

Kenta Iwasaki 140 Dec 28, 2022
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 3.5k Dec 29, 2022
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 208 Nov 21, 2022
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 7.1k Jan 2, 2023
A Go API for the V8 javascript engine.

V8 Bindings for Go The v8 bindings allow a user to execute javascript from within a go executable. The bindings are tested to work with several recent

Augusto Roman 383 Dec 15, 2022
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 2.4k Jan 9, 2023