| 
									
										
										
										
											2008-07-10 17:21:23 -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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 18:05:00 -07:00
										 |  |  | package Globals | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The following types should really be in their respective files | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | // (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. | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export Object | 
					
						
							|  |  |  | type Object struct { | 
					
						
							|  |  |  | 	mark bool;  // mark => object marked for export | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	pos int;  // source position | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 	kind int; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	ident string; | 
					
						
							|  |  |  | 	typ *Type; | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | // 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; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	pkg *Package; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export List | 
					
						
							|  |  |  | type List struct { | 
					
						
							|  |  |  | 	len_ int; | 
					
						
							|  |  |  | 	first, last *Elem; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export Scope | 
					
						
							|  |  |  | type Scope struct { | 
					
						
							|  |  |  | 	parent *Scope; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	entries *List; | 
					
						
							| 
									
										
										
										
											2008-07-15 19:59:00 -07:00
										 |  |  | 	// entries *map[string] *Object;  // doesn't work properly | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | export Compilation | 
					
						
							|  |  |  | type Compilation struct { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	// TODO use open arrays eventually | 
					
						
							|  |  |  | 	pkgs [256] *Package;  // pkgs[0] is the current package | 
					
						
							|  |  |  | 	npkgs int; | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Creation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export NewObject | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func NewObject(pos, kind int, ident string) *Object { | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	obj := new(Object); | 
					
						
							|  |  |  | 	obj.mark = false; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	obj.pos = pos; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	typ.ref = -1; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	typ.form = form; | 
					
						
							|  |  |  | 	return typ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | export NewPackage; | 
					
						
							|  |  |  | func NewPackage(file_name string) *Package { | 
					
						
							|  |  |  | 	pkg := new(Package); | 
					
						
							|  |  |  | 	pkg.ref = -1; | 
					
						
							|  |  |  | 	pkg.file_name = file_name; | 
					
						
							|  |  |  | 	return pkg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | export NewCompilation; | 
					
						
							|  |  |  | func NewCompilation() *Compilation { | 
					
						
							|  |  |  | 	comp := new(Compilation); | 
					
						
							|  |  |  | 	return comp; | 
					
						
							| 
									
										
										
										
											2008-07-17 14:53:13 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // 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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Scope methods | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | func (scope *Scope) Lookup(ident string) *Object { | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	var p *Elem; | 
					
						
							|  |  |  | 	for p = scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		if p.obj.ident == ident { | 
					
						
							|  |  |  | 			return p.obj; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | 	return nil; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (scope *Scope) Insert(obj *Object) { | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	if scope.Lookup(obj.ident) != nil { | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		panic "obj already inserted"; | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	scope.entries.AddObj(obj); | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (scope *Scope) InsertImport(obj *Object) *Object { | 
					
						
							| 
									
										
										
										
											2008-07-14 16:57:42 -07:00
										 |  |  | 	 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"; | 
					
						
							| 
									
										
										
										
											2008-07-10 17:21:23 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Compilation methods | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (C *Compilation) Lookup(file_name string) *Package { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	for i := 0; i < C.npkgs; i++ { | 
					
						
							|  |  |  | 		pkg := C.pkgs[i]; | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | 		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"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	C.pkgs[C.npkgs] = pkg; | 
					
						
							|  |  |  | 	C.npkgs++; | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } |