mirror of
https://github.com/golang/go.git
synced 2025-05-29 11:25:43 +00:00
first primitive cut at resolving missing imports automatically:
if an import file is missing, the corresponding source is compiled automatically, if found R=r OCL=13990 CL=13990
This commit is contained in:
parent
4addd94687
commit
bc13a1a374
@ -17,18 +17,25 @@ import Printer "printer"
|
|||||||
import Verifier "verifier"
|
import Verifier "verifier"
|
||||||
|
|
||||||
|
|
||||||
export func Compile(comp *Globals.Compilation, file_name string) {
|
export func Compile(flags *Globals.Flags, filename string) {
|
||||||
src, ok := sys.readfile(file_name);
|
// setup compilation
|
||||||
|
comp := new(Globals.Compilation);
|
||||||
|
comp.flags = flags;
|
||||||
|
comp.Compile = &Compile;
|
||||||
|
|
||||||
|
src, ok := sys.readfile(filename);
|
||||||
if !ok {
|
if !ok {
|
||||||
print "cannot open ", file_name, "\n"
|
print "cannot open ", filename, "\n"
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print filename, "\n";
|
||||||
|
|
||||||
scanner := new(Scanner.Scanner);
|
scanner := new(Scanner.Scanner);
|
||||||
scanner.Open(file_name, src);
|
scanner.Open(filename, src);
|
||||||
|
|
||||||
var tstream *chan *Scanner.Token;
|
var tstream *chan *Scanner.Token;
|
||||||
if comp.flags.pscan {
|
if comp.flags.token_chan {
|
||||||
tstream = new(chan *Scanner.Token, 100);
|
tstream = new(chan *Scanner.Token, 100);
|
||||||
go scanner.Server(tstream);
|
go scanner.Server(tstream);
|
||||||
}
|
}
|
||||||
@ -41,15 +48,15 @@ export func Compile(comp *Globals.Compilation, file_name string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !comp.flags.semantic_checks {
|
if !comp.flags.ast {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Verifier.Verify(comp);
|
Verifier.Verify(comp);
|
||||||
|
|
||||||
if comp.flags.print_export {
|
if comp.flags.print_interface {
|
||||||
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
|
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Export.Export(comp, file_name);
|
Export.Export(comp, filename);
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,12 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
|
|||||||
print "exporting to ", file_name, "\n";
|
print "exporting to ", file_name, "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write magic bits
|
||||||
|
magic := Globals.MAGIC_obj_file; // TODO remove once len(constant) works
|
||||||
|
for i := 0; i < len(magic); i++ {
|
||||||
|
E.WriteByte(magic[i]);
|
||||||
|
}
|
||||||
|
|
||||||
// Predeclared types are "pre-exported".
|
// Predeclared types are "pre-exported".
|
||||||
// TODO run the loop below only in debug mode
|
// TODO run the loop below only in debug mode
|
||||||
{ i := 0;
|
{ i := 0;
|
||||||
@ -279,5 +285,5 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
|
|||||||
|
|
||||||
export func Export(comp* Globals.Compilation, pkg_name string) {
|
export func Export(comp* Globals.Compilation, pkg_name string) {
|
||||||
var E Exporter;
|
var E Exporter;
|
||||||
(&E).Export(comp, Utils.FixExt(Utils.BaseName(pkg_name)));
|
(&E).Export(comp, Utils.TrimExt(Utils.BaseName(pkg_name), Globals.src_file_ext) + Globals.obj_file_ext);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,18 @@
|
|||||||
package Globals
|
package Globals
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
|
||||||
|
export const (
|
||||||
|
MAGIC_obj_file = "/*go.7*/"; // anything, really
|
||||||
|
src_file_ext = ".go";
|
||||||
|
obj_file_ext = ".7";
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The following types should really be in their respective files
|
// The following types should really be in their respective files
|
||||||
// (object.go, type.go, scope.go, package.go, compilation.go, etc.) but
|
// (object.go, type.go, scope.go, package.go, compilation.go, etc.) but
|
||||||
// they refer to each other and we don't know how to handle forward
|
// they refer to each other and we don't know how to handle forward
|
||||||
@ -60,16 +72,28 @@ export type Scope struct {
|
|||||||
|
|
||||||
export type Flags struct {
|
export type Flags struct {
|
||||||
debug bool;
|
debug bool;
|
||||||
print_export bool;
|
object_filename string;
|
||||||
semantic_checks bool;
|
update_packages bool;
|
||||||
verbose int;
|
print_interface bool;
|
||||||
sixg bool; // 6g compatibility
|
verbosity uint;
|
||||||
pscan bool; // parallel scanning using a token channel
|
sixg bool;
|
||||||
|
|
||||||
|
scan bool;
|
||||||
|
parse bool;
|
||||||
|
ast bool;
|
||||||
|
deps bool;
|
||||||
|
token_chan bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Compilation struct {
|
export type Compilation struct {
|
||||||
|
// envionment
|
||||||
flags *Flags;
|
flags *Flags;
|
||||||
|
Error *func(comp *Compilation); // TODO complete this
|
||||||
|
Import *func(comp *Compilation, data string) *Package;
|
||||||
|
Export *func(comp *Compilation) string;
|
||||||
|
Compile *func(flags *Flags, filename string); // TODO remove this eventually
|
||||||
|
|
||||||
// TODO use open arrays eventually
|
// TODO use open arrays eventually
|
||||||
pkg_list [256] *Package; // pkg_list[0] is the current package
|
pkg_list [256] *Package; // pkg_list[0] is the current package
|
||||||
pkg_ref int;
|
pkg_ref int;
|
||||||
@ -150,13 +174,6 @@ export func NewScope(parent *Scope) *Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func NewCompilation(flags *Flags) *Compilation {
|
|
||||||
comp := new(Compilation);
|
|
||||||
comp.flags = flags;
|
|
||||||
return comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Object methods
|
// Object methods
|
||||||
|
|
||||||
|
@ -9,49 +9,80 @@ import Globals "globals"
|
|||||||
import Compilation "compilation"
|
import Compilation "compilation"
|
||||||
|
|
||||||
|
|
||||||
// For now we are not using the flags package to minimize
|
|
||||||
// external dependencies, and because the requirements are
|
|
||||||
// very minimal at this point.
|
|
||||||
|
|
||||||
func PrintHelp() {
|
func PrintHelp() {
|
||||||
print "go in go (", Build.time, ")\n";
|
print
|
||||||
print "usage:\n";
|
"go (" + Build.time + ")\n" +
|
||||||
print " go { flag | file }\n";
|
"usage:\n" +
|
||||||
print " -d print debug information\n";
|
" go { flag } { file }\n" +
|
||||||
print " -p print export\n";
|
" -d debug mode, additional self tests and prints\n" +
|
||||||
print " -s enable semantic checks\n";
|
" -o filename explicit object filename\n" +
|
||||||
print " -v verbose mode\n";
|
" -r recursively update imported packages in current directory\n" +
|
||||||
print " -vv very verbose mode\n";
|
" -p print package interface\n" +
|
||||||
print " -6g 6g compatibility mode\n";
|
" -v [0 .. 3] verbosity level\n" +
|
||||||
print " -pscan scan and parse in parallel (use token channel)\n";
|
" -6g 6g compatibility mode\n" +
|
||||||
|
" -scan scan only, print tokens\n" +
|
||||||
|
" -parse parse only, print productions\n" +
|
||||||
|
" -ast analyse only, print ast\n" +
|
||||||
|
" -deps print package dependencies\n" +
|
||||||
|
" -token_chan use token channel to scan and parse in parallel\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var argno int = 1;
|
||||||
|
func Next() string {
|
||||||
|
arg := "";
|
||||||
|
if argno < sys.argc() {
|
||||||
|
arg = sys.argv(argno);
|
||||||
|
argno++;
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if sys.argc() <= 1 {
|
arg := Next();
|
||||||
PrintHelp();
|
|
||||||
sys.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if arg == "" {
|
||||||
|
PrintHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// collect flags and files
|
// collect flags and files
|
||||||
flags := new(Globals.Flags);
|
flags := new(Globals.Flags);
|
||||||
files := Globals.NewList();
|
files := Globals.NewList();
|
||||||
for i := 1; i < sys.argc(); i++ {
|
for arg != "" {
|
||||||
switch arg := sys.argv(i); arg {
|
switch arg {
|
||||||
case "-d": flags.debug = true;
|
case "-d": flags.debug = true;
|
||||||
case "-p": flags.print_export = true;
|
case "-o": flags.object_filename = Next();
|
||||||
case "-s": flags.semantic_checks = true;
|
print "note: -o flag ignored at the moment\n";
|
||||||
case "-v": flags.verbose = 1;
|
case "-r": flags.update_packages = true;
|
||||||
case "-vv": flags.verbose = 2;
|
case "-p": flags.print_interface = true;
|
||||||
|
case "-v":
|
||||||
|
arg = Next();
|
||||||
|
switch arg {
|
||||||
|
case "0", "1", "2", "3":
|
||||||
|
flags.verbosity = uint(arg[0] - '0');
|
||||||
|
default:
|
||||||
|
// anything else is considered the next argument
|
||||||
|
flags.verbosity = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
case "-6g": flags.sixg = true;
|
case "-6g": flags.sixg = true;
|
||||||
case "-pscan": flags.pscan = true;
|
case "-scan": flags.scan = true;
|
||||||
|
print "note: -scan flag ignored at the moment\n";
|
||||||
|
case "-parse": flags.parse = true;
|
||||||
|
print "note: -parse flag ignored at the moment\n";
|
||||||
|
case "-ast": flags.ast = true;
|
||||||
|
case "-deps": flags.deps = true;
|
||||||
|
print "note: -deps flag ignored at the moment\n";
|
||||||
|
case "-token_chan": flags.token_chan = true;
|
||||||
default: files.AddStr(arg);
|
default: files.AddStr(arg);
|
||||||
}
|
}
|
||||||
|
arg = Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile files
|
// compile files
|
||||||
for p := files.first; p != nil; p = p.next {
|
for p := files.first; p != nil; p = p.next {
|
||||||
comp := Globals.NewCompilation(flags);
|
Compilation.Compile(flags, p.str);
|
||||||
Compilation.Compile(comp, p.str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,6 +264,66 @@ func (I *Importer) ReadObject() *Globals.Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func ReadObjectFile(filename string) (data string, ok bool) {
|
||||||
|
data, ok = sys.readfile(filename + Globals.obj_file_ext);
|
||||||
|
magic := Globals.MAGIC_obj_file; // TODO remove once len(constant) works
|
||||||
|
if ok && len(data) >= len(magic) && data[0 : len(magic)] == magic {
|
||||||
|
return data, ok;
|
||||||
|
}
|
||||||
|
return "", false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func ReadSourceFile(filename string) (data string, ok bool) {
|
||||||
|
data, ok = sys.readfile(filename + Globals.src_file_ext);
|
||||||
|
return data, ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func ReadImport(comp* Globals.Compilation, filename string, update bool) (data string, ok bool) {
|
||||||
|
if filename == "" {
|
||||||
|
panic "illegal package file name";
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if it just works
|
||||||
|
data, ok = ReadObjectFile(filename);
|
||||||
|
if ok {
|
||||||
|
return data, ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
if filename[0] == '/' {
|
||||||
|
// absolute path
|
||||||
|
panic `don't know how to handle absolute import file path "` + filename + `"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// relative path
|
||||||
|
// try relative to the $GOROOT/pkg directory
|
||||||
|
std_filename := Utils.GOROOT + "/pkg/" + filename;
|
||||||
|
data, ok = ReadObjectFile(std_filename);
|
||||||
|
if ok {
|
||||||
|
return data, ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !update {
|
||||||
|
return "", false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO BIG HACK - fix this!
|
||||||
|
// look for a src file
|
||||||
|
// see if it just works
|
||||||
|
data, ok = ReadSourceFile(filename);
|
||||||
|
if ok {
|
||||||
|
comp.Compile(comp.flags, filename + Globals.src_file_ext);
|
||||||
|
data, ok = ReadImport(comp, filename, false);
|
||||||
|
if ok {
|
||||||
|
return data, ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.Package {
|
func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.Package {
|
||||||
I.comp = comp;
|
I.comp = comp;
|
||||||
I.debug = comp.flags.debug;
|
I.debug = comp.flags.debug;
|
||||||
@ -276,7 +336,8 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
|
|||||||
print "importing from ", file_name, "\n";
|
print "importing from ", file_name, "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, ok := sys.readfile(file_name);
|
// read file and check magic bits
|
||||||
|
buf, ok := ReadImport(comp, file_name, comp.flags.update_packages);
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@ -305,5 +366,5 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
|
|||||||
|
|
||||||
export func Import(comp* Globals.Compilation, pkg_name string) *Globals.Package {
|
export func Import(comp* Globals.Compilation, pkg_name string) *Globals.Package {
|
||||||
var I Importer;
|
var I Importer;
|
||||||
return (&I).Import(comp, Utils.FixExt(pkg_name));
|
return (&I).Import(comp, pkg_name);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import AST "ast"
|
|||||||
export type Parser struct {
|
export type Parser struct {
|
||||||
comp *Globals.Compilation;
|
comp *Globals.Compilation;
|
||||||
semantic_checks bool;
|
semantic_checks bool;
|
||||||
verbose, indent int;
|
verbose, indent uint;
|
||||||
S *Scanner.Scanner;
|
S *Scanner.Scanner;
|
||||||
C *chan *Scanner.Token;
|
C *chan *Scanner.Token;
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ func (P *Parser) Next() {
|
|||||||
|
|
||||||
func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, C *chan *Scanner.Token) {
|
func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, C *chan *Scanner.Token) {
|
||||||
P.comp = comp;
|
P.comp = comp;
|
||||||
P.semantic_checks = comp.flags.semantic_checks;
|
P.semantic_checks = comp.flags.ast;
|
||||||
P.verbose = comp.flags.verbose;
|
P.verbose = comp.flags.verbosity;
|
||||||
P.indent = 0;
|
P.indent = 0;
|
||||||
P.S = S;
|
P.S = S;
|
||||||
P.C = C;
|
P.C = C;
|
||||||
|
@ -223,7 +223,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Provide column information in error messages for gri only...
|
// Provide column information in error messages for gri only...
|
||||||
VerboseMsgs = Utils.GetEnv("USER") == "gri";
|
VerboseMsgs = Utils.USER == "gri";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,34 @@
|
|||||||
package Utils
|
package Utils
|
||||||
|
|
||||||
|
|
||||||
|
// Environment
|
||||||
|
export var
|
||||||
|
GOARCH,
|
||||||
|
GOOS,
|
||||||
|
GOROOT,
|
||||||
|
USER string;
|
||||||
|
|
||||||
|
|
||||||
|
func GetEnv(key string) string {
|
||||||
|
n := len(key);
|
||||||
|
for i := 0; i < sys.envc(); i++ {
|
||||||
|
v := sys.envv(i);
|
||||||
|
if v[0 : n] == key {
|
||||||
|
return v[n + 1 : len(v)]; // +1: trim "="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
GOARCH = GetEnv("GOARCH");
|
||||||
|
GOOS = GetEnv("GOOS");
|
||||||
|
GOROOT = GetEnv("GOROOT");
|
||||||
|
USER = GetEnv("USER");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export func BaseName(s string) string {
|
export func BaseName(s string) string {
|
||||||
// TODO this is not correct for non-ASCII strings!
|
// TODO this is not correct for non-ASCII strings!
|
||||||
i := len(s) - 1;
|
i := len(s) - 1;
|
||||||
@ -18,22 +46,10 @@ export func BaseName(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func FixExt(s string) string {
|
export func TrimExt(s, ext string) string {
|
||||||
i := len(s) - 3; // 3 == len(".go");
|
i := len(s) - len(ext);
|
||||||
if i >= 0 && s[i : len(s)] == ".go" {
|
if i >= 0 && s[i : len(s)] == ext {
|
||||||
s = s[0 : i];
|
s = s[0 : i];
|
||||||
}
|
}
|
||||||
return s + ".7";
|
return s;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export func GetEnv(key string) string {
|
|
||||||
n := len(key);
|
|
||||||
for i := 0; i < sys.envc(); i++ {
|
|
||||||
v := sys.envv(i);
|
|
||||||
if v[0 : n] == key {
|
|
||||||
return v[n + 1 : len(v)]; // +1: skip "="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user