mirror of
https://github.com/golang/go
synced 2024-11-19 06:04:39 -07:00
315 lines
5.7 KiB
Go
315 lines
5.7 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 Importer
|
||
|
|
||
|
import Globals "globals"
|
||
|
import Object "object"
|
||
|
import Type "type"
|
||
|
import Universe "universe"
|
||
|
|
||
|
|
||
|
type Importer struct {
|
||
|
comp *Globals.Compilation;
|
||
|
debug bool;
|
||
|
buf string;
|
||
|
pos int;
|
||
|
pkgs [256] *Globals.Package;
|
||
|
npkgs int;
|
||
|
types [1024] *Globals.Type;
|
||
|
ntypes int;
|
||
|
};
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadType() *Globals.Type;
|
||
|
func (I *Importer) ReadObject(tag int) *Globals.Object;
|
||
|
func (I *Importer) ReadPackage() *Globals.Package;
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadByte() byte {
|
||
|
x := I.buf[I.pos];
|
||
|
I.pos++;
|
||
|
/*
|
||
|
if E.debug {
|
||
|
print " ", x;
|
||
|
}
|
||
|
*/
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadInt() int {
|
||
|
x := 0;
|
||
|
s := 0; // TODO eventually Go will require this to be a uint!
|
||
|
b := I.ReadByte();
|
||
|
for b < 128 {
|
||
|
x |= int(b) << s;
|
||
|
s += 7;
|
||
|
b = I.ReadByte();
|
||
|
}
|
||
|
// b >= 128
|
||
|
x |= ((int(b) - 192) << s);
|
||
|
/*
|
||
|
if I.debug {
|
||
|
print " #", x;
|
||
|
}
|
||
|
*/
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadString() string {
|
||
|
var buf [256] byte; // TODO this needs to be fixed
|
||
|
n := I.ReadInt();
|
||
|
for i := 0; i < n; i++ {
|
||
|
buf[i] = I.ReadByte();
|
||
|
}
|
||
|
s := string(buf)[0 : n];
|
||
|
if I.debug {
|
||
|
print ` "`, s, `"`;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadObjTag() int {
|
||
|
tag := I.ReadInt();
|
||
|
if tag < 0 {
|
||
|
panic "tag < 0";
|
||
|
}
|
||
|
if I.debug {
|
||
|
print "\nObj: ", tag; // obj kind
|
||
|
}
|
||
|
return tag;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadTypeTag() int {
|
||
|
tag := I.ReadInt();
|
||
|
if I.debug {
|
||
|
if tag > 0 {
|
||
|
print "\nTyp ", I.ntypes, ": ", tag; // type form
|
||
|
} else {
|
||
|
print " [Typ ", -tag, "]"; // type ref
|
||
|
}
|
||
|
}
|
||
|
return tag;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadPackageTag() int {
|
||
|
tag := I.ReadInt();
|
||
|
if I.debug {
|
||
|
if tag > 0 {
|
||
|
print "\nPkg ", I.npkgs, ": ", tag; // package tag
|
||
|
} else {
|
||
|
print " [Pkg ", -tag, "]"; // package ref
|
||
|
}
|
||
|
}
|
||
|
return tag;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadTypeField() *Globals.Object {
|
||
|
fld := Globals.NewObject(0, Object.VAR, "");
|
||
|
fld.typ = I.ReadType();
|
||
|
return fld;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadScope() *Globals.Scope {
|
||
|
if I.debug {
|
||
|
print " {";
|
||
|
}
|
||
|
|
||
|
scope := Globals.NewScope(nil);
|
||
|
for n := I.ReadInt(); n > 0; n-- {
|
||
|
tag := I.ReadObjTag();
|
||
|
scope.Insert(I.ReadObject(tag));
|
||
|
}
|
||
|
|
||
|
if I.debug {
|
||
|
print " }";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadObject(tag int) *Globals.Object {
|
||
|
if tag == Object.PTYPE {
|
||
|
// primary type object - handled entirely by ReadType()
|
||
|
typ := I.ReadType();
|
||
|
if typ.obj.typ != typ {
|
||
|
panic "incorrect primary type";
|
||
|
}
|
||
|
return typ.obj;
|
||
|
|
||
|
} else {
|
||
|
ident := I.ReadString();
|
||
|
obj := Globals.NewObject(0, tag, ident);
|
||
|
obj.typ = I.ReadType();
|
||
|
obj.pnolev = I.ReadPackage().obj.pnolev;
|
||
|
|
||
|
switch (tag) {
|
||
|
default: fallthrough;
|
||
|
case Object.BAD: fallthrough;
|
||
|
case Object.PACKAGE: fallthrough;
|
||
|
case Object.PTYPE:
|
||
|
panic "UNREACHABLE";
|
||
|
|
||
|
case Object.CONST:
|
||
|
I.ReadInt(); // should set the value field
|
||
|
|
||
|
case Object.TYPE:
|
||
|
// nothing to do
|
||
|
|
||
|
case Object.VAR:
|
||
|
I.ReadInt(); // should set the address/offset field
|
||
|
|
||
|
case Object.FUNC:
|
||
|
I.ReadInt(); // should set the address/offset field
|
||
|
}
|
||
|
|
||
|
return obj;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadType() *Globals.Type {
|
||
|
tag := I.ReadTypeTag();
|
||
|
|
||
|
if tag <= 0 {
|
||
|
return I.types[-tag]; // type already imported
|
||
|
}
|
||
|
|
||
|
typ := Globals.NewType(tag);
|
||
|
ptyp := typ; // primary type
|
||
|
ident := I.ReadString();
|
||
|
if (len(ident) > 0) {
|
||
|
// primary type
|
||
|
obj := Globals.NewObject(0, Object.TYPE, ident);
|
||
|
obj.typ = typ;
|
||
|
typ.obj = obj;
|
||
|
|
||
|
// canonicalize type
|
||
|
pkg := I.ReadPackage();
|
||
|
obj.pnolev = pkg.obj.pnolev;
|
||
|
obj = pkg.scope.InsertImport(obj);
|
||
|
|
||
|
ptyp = obj.typ;
|
||
|
}
|
||
|
I.types[I.ntypes] = ptyp;
|
||
|
I.ntypes++;
|
||
|
|
||
|
switch (tag) {
|
||
|
default: fallthrough;
|
||
|
case Type.UNDEF: fallthrough;
|
||
|
case Type.BAD: fallthrough;
|
||
|
case Type.NIL: fallthrough;
|
||
|
case Type.BOOL: fallthrough;
|
||
|
case Type.UINT: fallthrough;
|
||
|
case Type.INT: fallthrough;
|
||
|
case Type.FLOAT: fallthrough;
|
||
|
case Type.STRING: fallthrough;
|
||
|
case Type.ANY:
|
||
|
panic "UNREACHABLE";
|
||
|
|
||
|
case Type.ARRAY:
|
||
|
typ.len_ = I.ReadInt();
|
||
|
typ.elt = I.ReadTypeField();
|
||
|
|
||
|
case Type.MAP:
|
||
|
typ.key = I.ReadTypeField();
|
||
|
typ.elt = I.ReadTypeField();
|
||
|
|
||
|
case Type.CHANNEL:
|
||
|
typ.flags = I.ReadInt();
|
||
|
typ.elt = I.ReadTypeField();
|
||
|
|
||
|
case Type.FUNCTION:
|
||
|
typ.flags = I.ReadInt();
|
||
|
fallthrough;
|
||
|
case Type.STRUCT: fallthrough;
|
||
|
case Type.INTERFACE:
|
||
|
typ.scope = I.ReadScope();
|
||
|
|
||
|
case Type.POINTER: fallthrough;
|
||
|
case Type.REFERENCE:
|
||
|
typ.elt = I.ReadTypeField();
|
||
|
}
|
||
|
|
||
|
return ptyp; // only use primary type
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) ReadPackage() *Globals.Package {
|
||
|
tag := I.ReadPackageTag();
|
||
|
|
||
|
if (tag <= 0) {
|
||
|
return I.pkgs[-tag]; // package already imported
|
||
|
}
|
||
|
|
||
|
ident := I.ReadString();
|
||
|
file_name := I.ReadString();
|
||
|
key := I.ReadString();
|
||
|
pkg := I.comp.Lookup(file_name);
|
||
|
|
||
|
if pkg == nil {
|
||
|
// new package
|
||
|
pkg = Globals.NewPackage(file_name);
|
||
|
pkg.scope = Globals.NewScope(nil);
|
||
|
pkg = I.comp.InsertImport(pkg);
|
||
|
|
||
|
} else if (key != pkg.key) {
|
||
|
// package inconsistency
|
||
|
panic "package key inconsistency";
|
||
|
}
|
||
|
I.pkgs[I.npkgs] = pkg;
|
||
|
I.npkgs++;
|
||
|
|
||
|
return pkg;
|
||
|
}
|
||
|
|
||
|
|
||
|
func (I *Importer) Import(comp* Globals.Compilation, file_name string) {
|
||
|
if I.debug {
|
||
|
print "importing from ", file_name;
|
||
|
}
|
||
|
|
||
|
buf, ok := sys.readfile(file_name);
|
||
|
if !ok {
|
||
|
panic "import failed";
|
||
|
}
|
||
|
|
||
|
I.comp = comp;
|
||
|
I.debug = true;
|
||
|
I.buf = buf;
|
||
|
I.pos = 0;
|
||
|
I.npkgs = 0;
|
||
|
I.ntypes = 0;
|
||
|
|
||
|
// Predeclared types are "pre-exported".
|
||
|
for p := Universe.types.first; p != nil; p = p.next {
|
||
|
if p.typ.ref != I.ntypes {
|
||
|
panic "incorrect ref for predeclared type";
|
||
|
}
|
||
|
I.types[I.ntypes] = p.typ;
|
||
|
I.ntypes++;
|
||
|
}
|
||
|
|
||
|
pkg := I.ReadPackage();
|
||
|
for {
|
||
|
tag := I.ReadObjTag();
|
||
|
if tag == 0 {
|
||
|
break;
|
||
|
}
|
||
|
obj := I.ReadObject(tag);
|
||
|
obj.pnolev = pkg.obj.pnolev;
|
||
|
pkg.scope.InsertImport(obj);
|
||
|
}
|
||
|
|
||
|
if I.debug {
|
||
|
print "\n(", I.pos, " bytes)\n";
|
||
|
}
|
||
|
}
|