Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
105 lines (91 sloc) 2.2 KB
package main
import (
"flag"
"fmt"
"io/ioutil"
"knox/ast"
"knox/builtin"
"knox/emitter"
"knox/lexer"
"knox/parser"
"knox/typechecker"
"os"
"os/exec"
"path"
"path/filepath"
"time"
)
func main() {
// Flags
timeFlag := flag.Bool("time", false, "Print the time taken by each compiler phase.")
astFlag := flag.Bool("ast", false, "Print the AST.")
goFlag := flag.Bool("go", false, "Print the Go code.")
outFlag := flag.String("out", "", "Path for output files.")
nameFlag := flag.String("name", "", "Name for output executable.")
binaryFlag := flag.Bool("binary", true, "Generates executable.")
flag.Parse()
args := flag.Args()
if len(args) == 0 {
panic("Specify file to be compiled.")
}
code, err := ioutil.ReadFile(args[0]) // TODO: Support multiple files.
//code, err := ioutil.ReadFile("examples/chain.knox")
if err != nil {
panic(err)
}
// Lex, parse, and generate the AST.
start := time.Now()
l := lexer.New(string(code) + "\n")
p := parser.New(l)
a := p.Program()
elapsedParsing := time.Since(start)
if *astFlag {
ast.Print(a)
}
// Builtin functions.
// TODO: Build builtin first in case user's program conflicts.
a = *builtin.Init(&a)
// Type check.
start = time.Now()
typechecker.Analyze(&a)
elapsedTypeChecking := time.Since(start)
// Control flow analysis.
//cfa.Analyze(&a)
// Generate code.
start = time.Now()
output := emitter.Generate(&a)
elapsedEmitting := time.Since(start)
if *goFlag {
fmt.Println(output)
}
// Output code.
ex, err := os.Executable()
if err != nil {
panic(err)
}
local := filepath.Dir(ex) // Get current path.
outputDir := path.Join(local, *outFlag)
outputFile := path.Join(outputDir, "out.go") // TODO: Go files should use Knox file names.
binName := *nameFlag
if binName == "" {
binName = "out"
}
outputBin := path.Join(outputDir, binName)
werr := ioutil.WriteFile(outputFile, []byte(output), 0644)
if werr != nil {
panic(werr)
}
// Invoke Go compiler.
if *binaryFlag {
cmd := exec.Command("go", "build", "-o", outputBin, outputFile)
_, sterr := cmd.Output()
if sterr != nil {
panic(sterr)
}
}
if *timeFlag {
fmt.Println(elapsedParsing)
fmt.Println(elapsedTypeChecking)
fmt.Println(elapsedEmitting)
}
}
You can’t perform that action at this time.