radrow / latte

x86 compiler of Latte – statically typed object oriented programming language inspired by Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Latte

A simple object-oriented programming language compiler written as an assesment task for MIMUW Compiler Construction course.

Build & Installation

To build the compiler one needs stack program installed. The Makefile will try to search for it in PATH and in places that could be used on MIMUW machines. If you don’t have stack, please navigate to their website.

The make script will automatically download all dependencies. They can be inspected in the configuration file package.yaml. Please note that it may require some free disk space and internet connection, as it will download GHC along with required libraries.

Project structure

Standard stack style is in use.

Main part of code is settled in the src folder which is divided to Frontend and Backend subfolders. In the former one there is whole logic related to parsing, typechecking, AST optimization and intermediate representation. The latter contains final compiler parts – currently only x86-32bit one.

Directory stdlib contains standard library implemented in C language. Note that the compiler makes use of the temporary folder (/tmp/ on linux) and therefore it needs access to it. I will use gcc and assume that it can be found in the PATH.

In the app folder there is the Main.hs file which is the entrypoint to the compiler.

Features

The language supports standard instructions like variable declarations, if-else statements, while loops, first order functions, etc. Uses strict and static type system.

Classes support inheritance and virtual method overriding. The syntax is very similar to the one known from Java. Example:

class Base {
  new() { }

  new smart(int x) {
    if (x == 0) {
      Sub1 o;
      return o;
    } else if (x == 1) {
      Sub2 o;
      return o;
    } else if (x == 2) {
      Sub3 o;
      return o;
    } else return this;
  }

  public int f(int x) {
    printInt(x);
    return 21;
  }
}

class Sub1 extends Base {
  int f(int x) {
    printInt(x);
    return 42;
  }
}
class Sub2 extends Base {
  int f(int x) {
    printInt(x);
    return super.f(x) + 10000;
  }
}
class Sub3 extends Base {}

int main() {
  printInt(new Base().f(-1));
  printInt(new Base.smart(0).f(0));
  printInt(new Base.smart(1).f(1));
  printInt(new Base.smart(2).f(2));
  printInt(new Base.smart(3).f(3));
  return 0;
}

One of the features that goes beyond the standard conventions is a more functional approach to constructors. Each of those actually returns the newly created instance (this if not explicitly stated). This means that they are capable of returning any other arbitrarily constructed object of their subclass. This feature can be treated as a built-in support for the factory design pattern. Moreover, the constructors can have names (awesome, isn’t it?).

Optimizations

The compiler performs some basic expression evaluation and constant propagation (does not inline functions tho). Dead code elimination is also supported. TCO will optimize functions where all self references are in tail positions. As the last thing it does peephole optimization on produced assembly.

TODO: reasonable register allocation, because the current one is bruteforced

About

x86 compiler of Latte – statically typed object oriented programming language inspired by Java

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Haskell 98.8%Language:C 0.8%Language:Makefile 0.3%