Skip to content

Latest commit

 

History

History
115 lines (95 loc) · 5.27 KB

README.org

File metadata and controls

115 lines (95 loc) · 5.27 KB

gocool

http://unmaintained.tech/badge.svg

Go implementation of the Cool programming language.

This repository contains a Golang implementation of the homeworks for the Coursera compilers class.

Parts

The compiler is divided into four parts, corresponding to the four programming homework assignments: lexing, scanning, typechecking, and compilation. The four shell scripts testlexer.sh, testparser.sh, testtypes.sh, and testcgen.sh test each of these four parts. The test cases are obtained by running the “grading.pl” script for each homework, and copying the test input and output. Minor changes have been made, as advised in the homework instructions, typically with regard to exact line numbers, although an effort has been made to match the examples.

Lexer

The lexer is a simple hand-written lexer, defined in parser/lex.go. It is a modified version of the go template lexer, copied and modified. For more background, read or watch Rob Pike’s excellent talk, Lexical Scanning in Go.

Parser

The parser is a yacc-generated LALR(1) parser. Similarities to Russ Cox’s C parser are due to the fact that it was frequently studied while wrestling with yacc. The AST classes in ast.go were defined by hand, and parser/dump.go contains functions that print them in the format used by the C++/Java Cool scaffolding code provided in the course materials.

Typechecking

There’s nothing interesting about the typechecking code: it was simply implemented bit by bit until all the tests passed. It does a bit of work (eg. symbol table generation) that could be considered part of code generation.

Compilation

The compiler (main code in cgen/cgen.go and cgen/expr.go) is about as simple as possible: a stack machine with an accumulator ($a0), and “self” saved in $s0 for easy reference. There are just a couple of things not suggested in the homework assignment: the “isa” tag-checking routine, and the embedding of prototype object addresses and initialization functions into the dispatch tables.

No effort was made to do any optimizations or to use more registers.

testcgen.sh runs all the tests three times: once with no garbage collection, once with garbage collection turned on, and once with both garbage collection and collect-after-every-allocation debugging turned on. If you set the environment variable NOSLOW before running it, it will skip the third phase.

Supplementary notes

MIPS registers

NumberNameFunctionCallee preserves?
$0zeroalways has value zero
$1atassembler temporary
$2-$3v0,v1function results. Can be temporary
$4-$7a0,a1,a2,a3function arguments
$8-$15,$24,$25t0,…,t7,t9temporary registers
$16-$23s0,…,s7saved registersYes
$26,$27k0,k1Reserved for OS kernel
$28gpglobal pointerYes
$29spstack pointerYes
$30fpframe pointerYes
$31rareturn address

Code generation

Stack machine with accumulator.

Accumulator: $a0: holds result of last expression evaluation. $s0 holds a stored copy of “self”. $sp points to next location in stack (so $sp+4 is the top of the stack) $t0, $t1, $t2 are temporary registers.

Activation Record

  • Return address
  • Old frame pointer
  • n arguments
  • NT(e) temporary locations
arg_1
arg_n
Old FP<– SP on entry
Return address
Temp NT(e)
Temp 1<– New FP
<– New SP

Object layout

-4FFFF - garbage collector tag
0class tag
4object size (in 32-bit words)
8dispatch pointer
12attributes

Strings:

12Length: pointer to an Int
16Characters, nul-terminated, zero-padded to next word