Compiler for a small language into x86-64 Assembly

Related tags

Compiler compiler
Overview

Compiler

This project is a small compiler, that compiles my own little language into X86-64 Assembly. It then uses yasm and ld to assemble and link into a Linux X86-64 executable.

But why?

I've always wanted to write a compiler myself! But just never got around to do it. So the current Coronavirus quarantine situation finally gives me enough time to tackle it myself.

And I was really impressed by people, that wrote solutions for last years adventofcode.com in their own language. So that is something I'd like to achieve :)

So no, no real reason other than - I like to work on challenging problems and found compilers intriguing.

How to run

  • go build
  • ./compiler <source_file>
  • ./executable

The compiler will always create an executable called executable. Additionally, it will create a file source.asm that contains the generated (not optimized) assembly.

Dependencies

Everything is written from scratch, there are no code dependencies. But to assemble and link the program into an executable, you need:

  • yasm
  • ld

The resulting Assembly also has no external dependencies (No C std lib, printing is implemented in Assembly directly).

Language influences

  • Go
  • C
  • Python
  • Lua

Features

  • Strong and static type system
  • Multiple return values from functions
  • Automatic packing/unpacking of multiple arguments and/or function returns
  • Function overloading
  • Function inlining (only for system functions right now)
  • Dynamic Arrays with an internal capacity, so not every append needs a new memory allocation
  • Int and Float types are always 64bit
  • Very Python-like array creation
  • Switch expressions match either values or general boolean expressions
  • Range-based Loops with index and element
  • Structs

Examples

See the compiler_test.go file for a lot more working examples :)

Print

// There are overloaded functions: print, println that work on floats and integers
println(5)
println(6.543)

Assignment

// Types are derived from the expressions!
a = 4
b = 5.6
c = true

Functions

fun abc(i int, j float) int, float, int {
    return i, j, 100
}
// Can be overloaded
fun abc(i int, j int) int, float, int {
    return i, 5.5, j
}
// ...
a, b, c = abc(5, 6.5)

Lists

// List of integers. Type derived from the expressions
list = [1, 2, 3, 4, 5]
// Empty list of integers with length 10. Type explicitely set
list2 = [](int, 10)
// Lists can naturally contain other lists
list3 = [list, list2]
// There are build-in functions, to get the length and capacity
println(len(list3))
println(cap(list3))

// You have to free them yourself
free(list)

// And some convenience functions to clear/reset the list without deallocating the memory:
// reset only resets the length, while clear overwrites the memory with 0s

reset(list)
clear(list)

// Build-in append/extend function, similar to the one in Go
// Careful ! append/extend works on the first argument. Depending on the available capacity, it will
// extend list or free list and create a completely new memory block, copy list and list2 over and return
// the new pointer!

list = append(list, 6)
list = extend(list, list2)

// Lists in functions/structs
fun abc(a []int) {
    // ...
}

Loops

list = [1,2,3,4,5]

for i = 0; i < len(list); i++ {
    // ...
}

for i,e : list {
    // i is the current index
    // e is the actual element: list[i]
}    

Switch

switch 4 {
case 1:
    println(1)
case 2, 3, 6:
    println(4)
case 5:
    println(5)
default:
    println(999)
}

switch {
case 2 > 3:
    println(1)
case 2 == 3:
    println(4)
default:
    println(888)
}

Structs

struct B {
    i int
    j int
}
struct A {
    i int
    j B
}

// Structs are created by calling a function with the same name and an exact match of parameters 
// that match the expected types of the struct.
// Internally, this is just syntax, not a function. So there is no overhead!
a = A(1, B(3, 4))
a.j.j = 100
println(a.i)
println(a.j.j)

Type conversions

// Build-in (inline) functions: int(), float()
println(int(5.5))
println(float(5))
You might also like...
Logexp - Logical expression compiler for golang

Logical Expression Compiler Functions: - Compile(exp string) - Match(text string

Transform Go code into it's AST

Welcome to go2ast 👋 Transform Go code into it's AST Usage echo "a := 1" | go run main.go Example output []ast.Stmt { &ast.AssignStmt {

Starlark in Go: the Starlark configuration language, implemented in Go

Starlark in Go This is the home of the Starlark in Go project. Starlark in Go is an interpreter for Starlark, implemented in Go. Starlark was formerly

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

A fast script language for Go
A fast script language for Go

The Tengo Language Tengo is a small, dynamic, fast, secure script language for Go. Tengo is fast and secure because it's compiled/executed as bytecode

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. https://vlang.io
Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in 1s with zero library dependencies. https://vlang.io

The V Programming Language vlang.io | Docs | Changelog | Speed | Contributing & compiler design Key Features of V Simplicity: the language can be lear

Elvish = Expressive Programming Language + Versatile Interactive Shell

Elvish: Expressive Programming Language + Versatile Interactive Shell Elvish is an expressive programming language and a versatile interactive shell,

Compiler for a small language into x86-64 Assembly

Compiler This project is a small compiler, that compiles my own little language into X86-64 Assembly. It then uses yasm and ld to assemble and link in

Generate x86 Assembly with Go

Generate x86 Assembly with Go avo makes high-performance Go assembly easier to write, review and maintain. The avo package presents a familiar assembl

ReCT-Go-Compiler - A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler - A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler A compiler for the ReCT programming language written in Golang

Assembly syntax that makes you feel like you're writing code in a high-level language.

shasm Assembly syntax that makes you feel like you're writing code in a high-level language. Shasm is not an Assembler. Shasm simply compiles Shasm sy

Go compiler made from scratch, which can compile itself. It's going to be the smallest and simplest go compiler in the world.

Babygo, a go compiler made from scratch Babygo is a small and simple go compiler. (Smallest and simplest in the world, I believe.) It is made from scr

Compiler as a Service is a compiler that is available over http/https and gRPC

BlakBoks(CaaS) Elasticsearch but for compiling untrusted code Compiler as a Service is a compiler that is available over http/2 and gRPC. Setup First

Experimental system call tracer for Linux x86-64, written in Go

gtrace A system call tracer for Linux x86-64. DISCLAIMER: This software is experimental and not considered stable. Do not use it in mission-critical e

🏃 An x86-64 assembler written in Go.

asm An x86-64 assembler written in Go. It is used by the Q programming language for machine code generation. Architectures Linux x86-64 (ELF binaries)

A Go unikernel running on x86 bare metal
A Go unikernel running on x86 bare metal

EggOS A Go unikernel running on x86 bare metal Run a single Go applications on x86 bare metal, written entirely in Go (only a small amount of C and so

Nanovms running in Docker x86 container for M1 Mac ARM64.

Docker Ops This project is an attempt to enable Nanos unikernels to be managed by Ops on non-intel architectures such as the Mac M1 ARM64. Unless ther

Make HMCL working in Apple Silicon Mac without x86 Java

M1MC Apple have used arm64 architecture on their new Macs. But Minecraft have no

Comments
  • return analysis is a bit naive

    return analysis is a bit naive

    Error should be emitted but isn't:

    fun test () int {
        for ;; {
            break
            return 0
        }    
    }
    

    Error emitted but shouldn't be:

    fun test (x int) int {
        if x == 0 { return 0 } else { }
    
        if x == 0 { return 0 } else { return 0 }
    }
    
    opened by zagortenay333 6
  • macOS usage

    macOS usage

    First of all, really cool project! I'd love to try it out, but I can't seem to get it to work. So I did

    go build
    brew install yasm
    ./compiler test.lang
    

    I've taken a look a test.lang, and I assume it's the example source file. Then I get the following error:

    ld: warning: No version-min specified on command line
    ld: warning: -arch not specified
    ld: warning: -macosx_version_min not specified, assuming 10.11
    ld: warning: ignoring file /var/folders/5p/9qqn9bds0kxf85ctpy0s12bm0000gn/T/061022517, file was built for unsupported file format ( 0x7F 0x45 0x4C 0x46 0x02 0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ) which is not the architecture being linked (x86_64): /var/folders/5p/9qqn9bds0kxf85ctpy0s12bm0000gn/T/061022517
    Undefined symbols for architecture x86_64:
      "_main", referenced from:
         implicit entry/start for main executable
    ld: symbol(s) not found for inferred architecture x86_64
    Error while linking object file - exit status 1
    

    Maybe I'm supposed to be linking something, like in C it would be, e.g. gcc -lcurl ..., but I'm not sure. Thanks for the help!

    opened by chammaaomar 3
Owner
Maurice Tollmien
Maurice Tollmien
Go compiler for small places. Microcontrollers, WebAssembly, and command-line tools. Based on LLVM.

TinyGo - Go compiler for small places TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (Wasm), and comma

TinyGo 11.9k Nov 21, 2022
A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler A compiler for the ReCT programming language written in Golang

null 8 Nov 17, 2022
A compiler from Go to JavaScript for running Go code in a browser

GopherJS - A compiler from Go to JavaScript GopherJS compiles Go code (golang.org) to pure JavaScript code. Its main purpose is to give you the opport

GopherJS 11.6k Nov 22, 2022
Automated compiler obfuscation for nim

Denim Makes compiling nim code with obfuscator-llvm easy! Windows only for now, but do you even need compiler obfuscation on other platforms? Setup In

Joe 105 Nov 9, 2022
Promise to the Go compiler that your Reads and Writes are well-behaved

noescape go get lukechampine.com/noescape noescape provides Read and Write functions that do not heap-allocate their argument. Normally, when you pas

Luke Champine 33 Jun 30, 2022
JIT compiler in Go

jit-compiler This is a Golang library containing an x86-64 assembler (see 'asm/') and a higher level intermediate representation that compiles down in

Bart Spaans 177 Nov 26, 2022
GopherLua: VM and compiler for Lua in Go

GopherLua: VM and compiler for Lua in Go. GopherLua is a Lua5.1 VM and compiler written in Go. GopherLua has a same goal with Lua: Be a scripting lang

Yusuke Inuzuka 5.1k Nov 23, 2022
A Lua 5.3 VM and compiler written in Go.

DCLua - Go Lua Compiler and VM: This is a Lua 5.3 VM and compiler written in Go. This is intended to allow easy embedding into Go programs, with minim

Milo Christiansen 900 Nov 17, 2022
The Project Oberon RISC compiler ported to Go.

oberon-compiler This is a port of the Project Oberon compiler for RISC-5 (not to be confused with RISC-V) from Oberon to Go. The compiled binaries can

null 6 Nov 4, 2022
The golang tool of the zig compiler automatically compiles different targets according to the GOOS GOARCH environment variable. You need to install zig.

The golang tool of the zig compiler automatically compiles different targets according to the GOOS GOARCH environment variable. You need to install zig.

dosgo 30 Nov 18, 2022