1
0
mirror of https://github.com/golang/go synced 2024-10-03 18:11:22 -06:00
go/usr/gri/pretty/globals.go
Robert Griesemer cb13c4d552 - more steps towards tracking idents in scopes
- snapshot of today

R=r
OCL=22247
CL=22247
2009-01-07 16:54:03 -08:00

232 lines
5.2 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
import "array"
// 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.
// ----------------------------------------------------------------------------
type Type struct
type Scope struct
type OldCompilation struct
// Object represents a language object, such as a constant, variable, type,
// etc. (kind). An objects is (pre-)declared at a particular position in the
// source code (pos), has a name (ident), a type (typ), and a package number
// or nesting level (pnolev).
export type Object struct {
exported bool;
pos int; // source position (< 0 if unknown position)
kind int;
ident string;
typ *Type; // nil for packages
pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
// attached values
block *array.Array; end int; // stats for function literals; end of block pos
}
export type Type struct {
ref int; // for exporting only: >= 0 means already exported
form int;
size int; // in bytes
len int; // array length, no. of function/method parameters (w/o recv)
aux int; // channel info
obj *Object; // primary type object or NULL
key *Type; // alias base type or map key
elt *Type; // aliased type, array, map, channel or pointer element type, function result type, tuple function type
scope *Scope; // forwards, structs, interfaces, functions
}
export type Package struct {
ref int; // for exporting only: >= 0 means already exported
file_name string;
key string;
obj *Object;
scope *Scope; // holds the (global) objects in this package
}
export type Scope struct {
parent *Scope;
entries map[string] *Object;
}
export type Environment struct {
Error *(comp *OldCompilation, pos int, msg string);
Import *(comp *OldCompilation, pkg_file string) *Package;
Export *(comp *OldCompilation, pkg_file string);
Compile *(comp *OldCompilation, src_file string);
}
export type OldCompilation struct {
// environment
env *Environment;
// TODO rethink the need for this here
src_file string;
src string;
// Error handling
nerrors int; // number of errors reported
errpos int; // last error position
// TODO use open arrays eventually
pkg_list [256] *Package; // pkg_list[0] is the current package
pkg_ref int;
}
export type Expr interface {
op() int; // node operation
pos() int; // source position
typ() *Type;
// ... more to come here
}
export type Stat interface {
// ... more to come here
}
// ----------------------------------------------------------------------------
// Creation
export var Universe_void_typ *Type // initialized by Universe to Universe.void_typ
export 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_void_typ;
obj.pnolev = 0;
return obj;
}
export func NewType(form int) *Type {
typ := new(Type);
typ.ref = -1; // not yet exported
typ.form = form;
return typ;
}
export func NewPackage(file_name string, obj *Object, scope *Scope) *Package {
pkg := new(Package);
pkg.ref = -1; // not yet exported
pkg.file_name = file_name;
pkg.key = "<the package key>"; // empty key means package forward declaration
pkg.obj = obj;
pkg.scope = scope;
return pkg;
}
export func NewScope(parent *Scope) *Scope {
scope := new(Scope);
scope.parent = parent;
scope.entries = make(map[string]*Object, 8);
return scope;
}
// ----------------------------------------------------------------------------
// 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;
return copy;
}
// ----------------------------------------------------------------------------
// Scope methods
func (scope *Scope) Lookup(ident string) *Object {
obj, found := scope.entries[ident];
if found {
return obj;
}
return nil;
}
func (scope *Scope) Add(obj* Object) {
scope.entries[obj.ident] = obj;
}
func (scope *Scope) Insert(obj *Object) {
if scope.Lookup(obj.ident) != nil {
panic("obj already inserted");
}
scope.Add(obj);
}
func (scope *Scope) InsertImport(obj *Object) *Object {
p := scope.Lookup(obj.ident);
if p == nil {
scope.Add(obj);
p = obj;
}
return p;
}
func (scope *Scope) Print() {
print("scope {");
for key := range scope.entries {
print("\n ", key);
}
print("\n}\n");
}
// ----------------------------------------------------------------------------
// Compilation methods
func (C *OldCompilation) Lookup(file_name string) *Package {
for i := 0; i < C.pkg_ref; i++ {
pkg := C.pkg_list[i];
if pkg.file_name == file_name {
return pkg;
}
}
return nil;
}
func (C *OldCompilation) Insert(pkg *Package) {
if C.Lookup(pkg.file_name) != nil {
panic("package already inserted");
}
pkg.obj.pnolev = C.pkg_ref;
C.pkg_list[C.pkg_ref] = pkg;
C.pkg_ref++;
}