1
0
mirror of https://github.com/golang/go synced 2024-09-29 15:24:28 -06:00
go/usr/gri/gosrc/globals.go
Robert Griesemer 0abbb8c76b more import/export stuff:
- no need to import/export predeclared types
- fix for receiver types
- cleanups
- added tests to Makefile

R=r
OCL=13728
CL=13730
2008-08-01 13:33:31 -07:00

349 lines
6.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 Globals
// The following types should really be in their respective files
// (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
// declared pointers across packages yet.
// ----------------------------------------------------------------------------
export Object
type Object struct {
exported bool;
pos int; // source position (< 0 if unknown position)
kind int;
ident string;
typ *Type;
pnolev int; // >= 0: package no., <= 0: level, 0: global level of compilation
scope *Scope; // which contains the object
}
export Type
type Type struct {
ref int; // for exporting only: >= 0 means already exported
form int;
flags int; // channels, functions
size int; // in bytes
len_ int; // array length, no. of parameters (w/o recv)
obj *Object; // primary type object or NULL
key *Type; // maps
elt *Type; // aliases, arrays, maps, channels, pointers
scope *Scope; // structs, interfaces, functions
}
export Package
type Package struct {
ref int; // for exporting only: >= 0 means already exported
file_name string;
key string;
obj *Object;
scope *Scope;
}
// TODO This is hideous! We need to have a decent way to do lists.
// Ideally open arrays that allow '+'.
type Elem struct {
next *Elem;
val int;
str string;
obj *Object;
typ *Type;
}
export List
type List struct {
len_ int;
first, last *Elem;
};
export Scope
type Scope struct {
parent *Scope;
entries *List;
// entries *map[string] *Object; // doesn't work properly
}
export Flags;
type Flags struct {
debug bool;
print_export bool;
semantic_checks bool;
verbose int;
sixg bool;
}
export Compilation
type Compilation struct {
flags *Flags;
// TODO use open arrays eventually
pkgs [256] *Package; // pkgs[0] is the current package
npkgs int;
}
export Expr
type Expr interface {
typ() *Type;
// ... more to come here
}
export Stat
type Stat interface {
// ... more to come here
}
// ----------------------------------------------------------------------------
// Creation
export Universe_undef_t
var Universe_undef_t *Type // initialized by Universe to Universe.undef_t
export NewObject
func NewObject(pos, kind int, ident string) *Object {
obj := new(Object);
obj.exported = false;
obj.pos = pos;
obj.kind = kind;
obj.ident = ident;
obj.typ = Universe_undef_t;
obj.pnolev = 0;
obj.scope = nil;
return obj;
}
export NewType
func NewType(form int) *Type {
typ := new(Type);
typ.ref = -1; // not yet exported
typ.form = form;
return typ;
}
export NewPackage;
func NewPackage(file_name string) *Package {
pkg := new(Package);
pkg.ref = -1; // not yet exported
pkg.file_name = file_name;
pkg.key = "<the package key>"; // TODO fix this
return pkg;
}
export NewList
func NewList() *List {
return new(List);
}
export NewScope
func NewScope(parent *Scope) *Scope {
scope := new(Scope);
scope.parent = parent;
scope.entries = NewList();
return scope;
}
export NewCompilation;
func NewCompilation(flags *Flags) *Compilation {
comp := new(Compilation);
comp.flags = flags;
return comp;
}
// ----------------------------------------------------------------------------
// Object methods
func (obj *Object) Copy() *Object {
copy := new(Object);
copy.exported = obj.exported;
copy.pos = obj.pos;
copy.kind = obj.kind;
copy.ident = obj.ident;
copy.typ = obj.typ;
copy.pnolev = obj.pnolev;
copy.scope = nil; // cannot be in the same scope (same ident!)
return copy;
}
// ----------------------------------------------------------------------------
// List methods
func (L* List) len_() int {
return L.len_;
}
func (L *List) at(i int) *Elem {
if i < 0 || L.len_ <= i {
panic "index out of bounds";
}
p := L.first;
for ; i > 0; i-- {
p = p.next;
}
return p;
}
func (L *List) Clear() {
L.len_, L.first, L.last = 0, nil, nil;
}
func (L *List) Add() *Elem {
L.len_++;
e := new(Elem);
if L.first == nil {
L.first = e;
} else {
L.last.next = e;
}
L.last = e;
return e;
}
func (L *List) IntAt(i int) int {
return L.at(i).val;
}
func (L *List) StrAt(i int) string {
return L.at(i).str;
}
func (L *List) ObjAt(i int) *Object {
return L.at(i).obj;
}
func (L *List) TypAt(i int) *Type {
return L.at(i).typ;
}
func (L *List) AddInt(val int) {
L.Add().val = val;
}
func (L *List) AddStr(str string) {
L.Add().str = str;
}
func (L *List) AddObj(obj *Object) {
L.Add().obj = obj;
}
func (L *List) AddTyp(typ *Type) {
L.Add().typ = typ;
}
// ----------------------------------------------------------------------------
// Scope methods
func (scope *Scope) Lookup(ident string) *Object {
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.ident == ident {
if p.obj.scope != scope {
panic "incorrect scope for object";
}
return p.obj;
}
}
return nil;
}
func (scope *Scope) Insert(obj *Object) {
if scope.Lookup(obj.ident) != nil {
panic "obj already inserted";
}
if obj.scope != nil {
panic "obj already in a scope";
}
scope.entries.AddObj(obj);
obj.scope = scope;
}
func (scope *Scope) InsertImport(obj *Object) *Object {
p := scope.Lookup(obj.ident);
if p == nil {
scope.Insert(obj);
p = obj;
}
return p;
}
func (scope *Scope) Print() {
print "scope {";
for p := scope.entries.first; p != nil; p = p.next {
print "\n ", p.obj.ident;
}
print "\n}\n";
}
// ----------------------------------------------------------------------------
// Compilation methods
func (C *Compilation) Lookup(file_name string) *Package {
for i := 0; i < C.npkgs; i++ {
pkg := C.pkgs[i];
if pkg.file_name == file_name {
return pkg;
}
}
return nil;
}
func (C *Compilation) Insert(pkg *Package) {
if C.Lookup(pkg.file_name) != nil {
panic "package already inserted";
}
pkg.obj.pnolev = C.npkgs;
C.pkgs[C.npkgs] = pkg;
C.npkgs++;
}
func (C *Compilation) InsertImport(pkg *Package) *Package {
p := C.Lookup(pkg.file_name);
if (p == nil) {
// no primary package found
C.Insert(pkg);
p = pkg;
}
return p;
}