mirror of
https://github.com/golang/go
synced 2024-11-20 11:04:56 -07:00
626d25065d
R=r OCL=22998 CL=22998
213 lines
4.1 KiB
Go
213 lines
4.1 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package Compilation
|
|
|
|
import (
|
|
"array";
|
|
"utf8";
|
|
OS "os";
|
|
Platform "platform";
|
|
Scanner "scanner";
|
|
Parser "parser";
|
|
AST "ast";
|
|
TypeChecker "typechecker";
|
|
)
|
|
|
|
|
|
func assert(b bool) {
|
|
if !b {
|
|
panic("assertion failed");
|
|
}
|
|
}
|
|
|
|
|
|
export type Flags struct {
|
|
Verbose bool;
|
|
Sixg bool;
|
|
Deps bool;
|
|
Columns bool;
|
|
Testmode bool;
|
|
Tokenchan bool;
|
|
Naming bool;
|
|
}
|
|
|
|
|
|
type errorHandler struct {
|
|
filename string;
|
|
src string;
|
|
nerrors int;
|
|
nwarnings int;
|
|
errpos int;
|
|
columns bool;
|
|
}
|
|
|
|
|
|
func (h *errorHandler) Init(filename, src string, columns bool) {
|
|
h.filename = filename;
|
|
h.src = src;
|
|
h.nerrors = 0;
|
|
h.nwarnings = 0;
|
|
h.errpos = 0;
|
|
h.columns = columns;
|
|
}
|
|
|
|
|
|
// Compute (line, column) information for a given source position.
|
|
func (h *errorHandler) LineCol(pos int) (line, col int) {
|
|
line = 1;
|
|
lpos := 0;
|
|
|
|
src := h.src;
|
|
if pos > len(src) {
|
|
pos = len(src);
|
|
}
|
|
|
|
for i := 0; i < pos; i++ {
|
|
if src[i] == '\n' {
|
|
line++;
|
|
lpos = i;
|
|
}
|
|
}
|
|
|
|
return line, utf8.RuneCountInString(src, lpos, pos - lpos);
|
|
}
|
|
|
|
|
|
func (h *errorHandler) ErrorMsg(pos int, msg string) {
|
|
print(h.filename, ":");
|
|
if pos >= 0 {
|
|
// print position
|
|
line, col := h.LineCol(pos);
|
|
print(line, ":");
|
|
if h.columns {
|
|
print(col, ":");
|
|
}
|
|
}
|
|
print(" ", msg, "\n");
|
|
|
|
h.nerrors++;
|
|
h.errpos = pos;
|
|
|
|
if h.nerrors >= 10 {
|
|
// TODO enable when done with name convention
|
|
//sys.Exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
func (h *errorHandler) Error(pos int, msg string) {
|
|
// only report errors that are sufficiently far away from the previous error
|
|
// in the hope to avoid most follow-up errors
|
|
const errdist = 20;
|
|
delta := pos - h.errpos; // may be negative!
|
|
if delta < 0 {
|
|
delta = -delta;
|
|
}
|
|
|
|
if delta > errdist || h.nerrors == 0 /* always report first error */ {
|
|
h.ErrorMsg(pos, msg);
|
|
}
|
|
}
|
|
|
|
|
|
func (h *errorHandler) Warning(pos int, msg string) {
|
|
panic("UNIMPLEMENTED");
|
|
}
|
|
|
|
|
|
export func Compile(src_file string, flags *Flags) (*AST.Program, int) {
|
|
src, ok := Platform.ReadSourceFile(src_file);
|
|
if !ok {
|
|
print("cannot open ", src_file, "\n");
|
|
return nil, 1;
|
|
}
|
|
|
|
var err errorHandler;
|
|
err.Init(src_file, src, flags.Columns);
|
|
|
|
var scanner Scanner.Scanner;
|
|
scanner.Init(&err, src, true, flags.Testmode);
|
|
|
|
var tstream <-chan *Scanner.Token;
|
|
if flags.Tokenchan {
|
|
tstream = scanner.TokenStream();
|
|
}
|
|
|
|
var parser Parser.Parser;
|
|
parser.Open(flags.Verbose, flags.Sixg, flags.Deps, flags.Naming, &scanner, tstream);
|
|
|
|
prog := parser.ParseProgram();
|
|
|
|
if err.nerrors == 0 {
|
|
TypeChecker.CheckProgram(&err, prog);
|
|
}
|
|
|
|
return prog, err.nerrors;
|
|
}
|
|
|
|
|
|
func fileExists(name string) bool {
|
|
fd, err := OS.Open(name, OS.O_RDONLY, 0);
|
|
if err == nil {
|
|
fd.Close();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
func addDeps(globalset map [string] bool, wset *array.Array, src_file string, flags *Flags) {
|
|
dummy, found := globalset[src_file];
|
|
if !found {
|
|
globalset[src_file] = true;
|
|
|
|
prog, nerrors := Compile(src_file, flags);
|
|
if nerrors > 0 {
|
|
return;
|
|
}
|
|
|
|
nimports := prog.Decls.Len();
|
|
if nimports > 0 {
|
|
print(src_file, ".6:\t");
|
|
|
|
localset := make(map [string] bool);
|
|
for i := 0; i < nimports; i++ {
|
|
decl := prog.Decls.At(i).(*AST.Decl);
|
|
assert(decl.Tok == Scanner.IMPORT && decl.Val.Tok == Scanner.STRING);
|
|
src := decl.Val.Obj.Ident;
|
|
src = src[1 : len(src) - 1]; // strip "'s
|
|
|
|
// ignore files when they are seen a 2nd time
|
|
dummy, found := localset[src];
|
|
if !found {
|
|
localset[src] = true;
|
|
if fileExists(src + ".go") {
|
|
wset.Push(src);
|
|
print(" ", src, ".6");
|
|
} else if
|
|
fileExists(Platform.GOROOT + "/pkg/" + src + ".6") ||
|
|
fileExists(Platform.GOROOT + "/pkg/" + src + ".a") {
|
|
|
|
} else {
|
|
// TODO should collect these and print later
|
|
//print("missing file: ", src, "\n");
|
|
}
|
|
}
|
|
}
|
|
print("\n\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export func ComputeDeps(src_file string, flags *Flags) {
|
|
globalset := make(map [string] bool);
|
|
wset := array.New(0);
|
|
wset.Push(src_file);
|
|
for wset.Len() > 0 {
|
|
addDeps(globalset, wset, wset.Pop().(string), flags);
|
|
}
|
|
}
|