| // 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) 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 { |
| mark bool; // mark => object marked for export |
| pos int; // source position |
| kind int; |
| ident string; |
| typ *Type; |
| pnolev int; // >= 0: package no., <= 0: level, 0: global level of compilation |
| } |
| |
| |
| 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 *Object; // maps |
| elt *Object; // arrays, maps, channels, pointers, references |
| 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; |
| str string; |
| obj *Object; |
| typ *Type; |
| pkg *Package; |
| } |
| |
| |
| 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 Compilation |
| type Compilation struct { |
| // TODO use open arrays eventually |
| pkgs [256] *Package; // pkgs[0] is the current package |
| npkgs int; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Creation |
| |
| export NewObject |
| func NewObject(pos, kind int, ident string) *Object { |
| obj := new(Object); |
| obj.mark = false; |
| obj.pos = pos; |
| obj.kind = kind; |
| obj.ident = ident; |
| obj.typ = nil; // Universe::undef_t; |
| obj.pnolev = 0; |
| return obj; |
| } |
| |
| |
| export NewType |
| func NewType(form int) *Type { |
| typ := new(Type); |
| typ.ref = -1; |
| typ.form = form; |
| return typ; |
| } |
| |
| |
| export NewPackage; |
| func NewPackage(file_name string) *Package { |
| pkg := new(Package); |
| pkg.ref = -1; |
| 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() *Compilation { |
| comp := new(Compilation); |
| return comp; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // 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) 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) 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) 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 { |
| var p *Elem; |
| for p = scope.entries.first; p != nil; p = p.next { |
| if p.obj.ident == ident { |
| return p.obj; |
| } |
| } |
| return nil; |
| } |
| |
| |
| func (scope *Scope) Insert(obj *Object) { |
| if scope.Lookup(obj.ident) != nil { |
| panic "obj already inserted"; |
| } |
| scope.entries.AddObj(obj); |
| } |
| |
| |
| 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 {"; |
| var p* Elem; |
| 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"; |
| } |
| 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; |
| } |