2008-12-16 19:02:22 -07:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
type Type struct
|
|
|
|
type Scope struct
|
|
|
|
type Elem 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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2008-12-19 04:05:37 -07:00
|
|
|
entries map[string] *Object;
|
2008-12-16 19:02:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2008-12-19 04:05:37 -07:00
|
|
|
|
2008-12-16 19:02:22 -07:00
|
|
|
// TODO rethink the need for this here
|
|
|
|
src_file string;
|
|
|
|
src string;
|
2008-12-19 04:05:37 -07:00
|
|
|
|
2008-12-16 19:02:22 -07:00
|
|
|
// Error handling
|
|
|
|
nerrors int; // number of errors reported
|
|
|
|
errpos int; // last error position
|
2008-12-19 04:05:37 -07:00
|
|
|
|
2008-12-16 19:02:22 -07:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO This is hideous! We need to have a decent way to do lists.
|
|
|
|
// Ideally open arrays that allow '+'.
|
|
|
|
|
|
|
|
export type Elem struct {
|
|
|
|
next *Elem;
|
|
|
|
val int;
|
|
|
|
str string;
|
|
|
|
obj *Object;
|
|
|
|
typ *Type;
|
|
|
|
expr Expr
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Creation
|
|
|
|
|
|
|
|
export var Universe_void_typ *Type // initialized by Universe to Universe.void_typ
|
|
|
|
|
|
|
|
export func NewObject(pos, kind int, ident string) *Object {
|
2008-12-19 04:05:37 -07:00
|
|
|
obj := new(*Object);
|
2008-12-16 19:02:22 -07:00
|
|
|
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 {
|
2008-12-19 04:05:37 -07:00
|
|
|
typ := new(*Type);
|
2008-12-16 19:02:22 -07:00
|
|
|
typ.ref = -1; // not yet exported
|
|
|
|
typ.form = form;
|
|
|
|
return typ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export func NewPackage(file_name string, obj *Object, scope *Scope) *Package {
|
2008-12-19 04:05:37 -07:00
|
|
|
pkg := new(*Package);
|
2008-12-16 19:02:22 -07:00
|
|
|
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 {
|
2008-12-19 04:05:37 -07:00
|
|
|
scope := new(*Scope);
|
2008-12-16 19:02:22 -07:00
|
|
|
scope.parent = parent;
|
|
|
|
scope.entries = new(map[string]*Object, 8);
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Object methods
|
|
|
|
|
|
|
|
func (obj *Object) Copy() *Object {
|
2008-12-19 04:05:37 -07:00
|
|
|
copy := new(*Object);
|
2008-12-16 19:02:22 -07:00
|
|
|
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++;
|
|
|
|
}
|