| 
									
										
										
										
											2008-07-15 15:37:14 -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 Exporter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Globals "globals" | 
					
						
							|  |  |  | import Object "object" | 
					
						
							|  |  |  | import Type "type" | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | import Universe "universe" | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | export Exporter  // really only want to export Export() | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | type Exporter struct { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	comp *Globals.Compilation; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	debug bool; | 
					
						
							|  |  |  | 	buf [4*1024] byte; | 
					
						
							|  |  |  | 	pos int; | 
					
						
							|  |  |  | 	pkg_ref int; | 
					
						
							|  |  |  | 	type_ref int; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteType(typ *Globals.Type); | 
					
						
							|  |  |  | func (E *Exporter) WriteObject(obj *Globals.Object); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | func (E *Exporter) WritePackage(pkg *Globals.Package); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteByte(x byte) { | 
					
						
							|  |  |  | 	E.buf[E.pos] = x; | 
					
						
							|  |  |  | 	E.pos++; | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	/* | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print " ", x; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteInt(x int) { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	/* | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print " #", x; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	for x < -64 || x >= 64 { | 
					
						
							|  |  |  | 		E.WriteByte(byte(x & 127)); | 
					
						
							|  |  |  | 		x = int(uint(x >> 7));  // arithmetic shift | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// -64 <= x && x < 64 | 
					
						
							|  |  |  | 	E.WriteByte(byte(x + 192)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteString(s string) { | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 		print ` "`, s, `"`; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	n := len(s); | 
					
						
							|  |  |  | 	E.WriteInt(n); | 
					
						
							|  |  |  | 	for i := 0; i < n; i++ { | 
					
						
							|  |  |  | 		E.WriteByte(s[i]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteObjTag(tag int) { | 
					
						
							|  |  |  | 	if tag < 0 { | 
					
						
							|  |  |  | 		panic "tag < 0"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 		print "\nObj: ", tag;  // obj kind | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteInt(tag); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteTypeTag(tag int) { | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		if tag > 0 { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 			print "\nTyp ", E.type_ref, ": ", tag;  // type form | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 			print " [Typ ", -tag, "]";  // type ref | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteInt(tag); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WritePackageTag(tag int) { | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		if tag > 0 { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 			print "\nPkg ", E.pkg_ref, ": ", tag;  // package no | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 			print " [Pkg ", -tag, "]";  // package ref | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteInt(tag); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteTypeField(fld *Globals.Object) { | 
					
						
							|  |  |  | 	if fld.kind != Object.VAR { | 
					
						
							|  |  |  | 		panic "fld.kind != Object.VAR"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteType(fld.typ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteScope(scope *Globals.Scope) { | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print " {"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// determine number of objects to export | 
					
						
							|  |  |  | 	n := 0; | 
					
						
							|  |  |  | 	for p := scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		if p.obj.mark { | 
					
						
							|  |  |  | 			n++; | 
					
						
							|  |  |  | 		}			 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// export the objects, if any | 
					
						
							|  |  |  | 	if n > 0 { | 
					
						
							|  |  |  | 		for p := scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			if p.obj.mark { | 
					
						
							|  |  |  | 				E.WriteObject(p.obj); | 
					
						
							|  |  |  | 			}			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print " }"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteObject(obj *Globals.Object) { | 
					
						
							|  |  |  | 	if obj == nil || !obj.mark { | 
					
						
							|  |  |  | 		panic "obj == nil || !obj.mark"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if obj.kind == Object.TYPE && obj.typ.obj == obj { | 
					
						
							|  |  |  | 		// primary type object - handled entirely by WriteType() | 
					
						
							|  |  |  | 		E.WriteObjTag(Object.PTYPE); | 
					
						
							|  |  |  | 		E.WriteType(obj.typ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		E.WriteObjTag(obj.kind); | 
					
						
							|  |  |  | 		E.WriteString(obj.ident); | 
					
						
							|  |  |  | 		E.WriteType(obj.typ); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		//E.WritePackage(E.comp.pkgs[obj.pnolev]); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		switch obj.kind { | 
					
						
							|  |  |  | 		case Object.CONST: | 
					
						
							|  |  |  | 			E.WriteInt(0);  // should be the correct value | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		case Object.TYPE: | 
					
						
							|  |  |  | 			// nothing to do | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		case Object.VAR: | 
					
						
							|  |  |  | 			E.WriteInt(0);  // should be the correct address/offset | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		case Object.FUNC: | 
					
						
							|  |  |  | 			E.WriteInt(0);  // should be the correct address/offset | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			print "obj.kind = ", obj.kind, "\n"; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 			panic "UNREACHABLE"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (E *Exporter) WriteType(typ *Globals.Type) { | 
					
						
							|  |  |  | 	if typ == nil { | 
					
						
							|  |  |  | 		panic "typ == nil"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if typ.ref >= 0 { | 
					
						
							|  |  |  | 		E.WriteTypeTag(-typ.ref);  // type already exported | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if typ.form <= 0 { | 
					
						
							|  |  |  | 		panic "typ.form <= 0"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteTypeTag(typ.form); | 
					
						
							|  |  |  | 	typ.ref = E.type_ref; | 
					
						
							|  |  |  | 	E.type_ref++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if typ.obj != nil { | 
					
						
							|  |  |  | 		if typ.obj.typ != typ { | 
					
						
							|  |  |  | 			panic "typ.obj.type() != typ";  // primary type | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		E.WriteString(typ.obj.ident); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 		E.WritePackage(E.comp.pkgs[typ.obj.pnolev]); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		E.WriteString(""); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch typ.form { | 
					
						
							|  |  |  | 	case Type.ARRAY: | 
					
						
							|  |  |  | 		E.WriteInt(typ.len_); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		E.WriteType(typ.elt); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.MAP: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		E.WriteType(typ.key); | 
					
						
							|  |  |  | 		E.WriteType(typ.elt); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.CHANNEL: | 
					
						
							|  |  |  | 		E.WriteInt(typ.flags); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		E.WriteType(typ.elt); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.FUNCTION: | 
					
						
							|  |  |  | 		E.WriteInt(typ.flags); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		E.WriteScope(typ.scope); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	case Type.STRUCT, Type.INTERFACE: | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		E.WriteScope(typ.scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	case Type.POINTER, Type.REFERENCE: | 
					
						
							|  |  |  | 		E.WriteType(typ.elt); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		print "typ.form = ", typ.form, "\n"; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		panic "UNREACHABLE"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 14:53:13 -07:00
										 |  |  | func (E *Exporter) WritePackage(pkg *Globals.Package) { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	if pkg.ref >= 0 { | 
					
						
							|  |  |  | 		E.WritePackageTag(-pkg.ref);  // package already exported | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if Object.PACKAGE <= 0 { | 
					
						
							|  |  |  | 		panic "Object.PACKAGE <= 0"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WritePackageTag(Object.PACKAGE); | 
					
						
							|  |  |  | 	pkg.ref = E.pkg_ref; | 
					
						
							|  |  |  | 	E.pkg_ref++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	E.WriteString(pkg.obj.ident); | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	E.WriteString(pkg.file_name); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	E.WriteString(pkg.key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | func (E *Exporter) Export(comp* Globals.Compilation, file_name string) { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:23:04 -07:00
										 |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print "exporting to ", file_name; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	E.comp = comp; | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	E.debug = true; | 
					
						
							|  |  |  | 	E.pos = 0; | 
					
						
							|  |  |  | 	E.pkg_ref = 0; | 
					
						
							|  |  |  | 	E.type_ref = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	// Predeclared types are "pre-exported". | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	// TODO run the loop below only in debug mode | 
					
						
							|  |  |  | 	{	i := 0; | 
					
						
							|  |  |  | 		for p := Universe.types.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			if p.typ.ref != i { | 
					
						
							|  |  |  | 				panic "incorrect ref for predeclared type"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			i++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	E.type_ref = Universe.types.len_; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	pkg := comp.pkgs[0]; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	E.WritePackage(pkg); | 
					
						
							|  |  |  | 	for p := pkg.scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		if p.obj.mark { | 
					
						
							|  |  |  | 			E.WriteObject(p.obj); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	E.WriteObjTag(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 		print "\n(", E.pos, " bytes)\n"; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	data := string(E.buf)[0 : E.pos]; | 
					
						
							|  |  |  | 	ok := sys.writefile(file_name, data); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:23:04 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		panic "export failed"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | } |