| 
									
										
										
										
											2008-07-18 14:04:21 -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 Importer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Globals "globals" | 
					
						
							|  |  |  | import Object "object" | 
					
						
							|  |  |  | import Type "type" | 
					
						
							|  |  |  | import Universe "universe" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | export Importer  // really only want to export Import() | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | type Importer struct { | 
					
						
							|  |  |  | 	comp *Globals.Compilation; | 
					
						
							|  |  |  | 	debug bool; | 
					
						
							|  |  |  | 	buf string; | 
					
						
							|  |  |  | 	pos int; | 
					
						
							|  |  |  | 	pkgs [256] *Globals.Package; | 
					
						
							|  |  |  | 	npkgs int; | 
					
						
							|  |  |  | 	types [1024] *Globals.Type; | 
					
						
							|  |  |  | 	ntypes int; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadType() *Globals.Type; | 
					
						
							|  |  |  | func (I *Importer) ReadObject(tag int) *Globals.Object; | 
					
						
							|  |  |  | func (I *Importer) ReadPackage() *Globals.Package; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadByte() byte { | 
					
						
							|  |  |  | 	x := I.buf[I.pos]; | 
					
						
							|  |  |  | 	I.pos++; | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	if E.debug { | 
					
						
							|  |  |  | 		print " ", x; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadInt() int { | 
					
						
							|  |  |  | 	x := 0; | 
					
						
							|  |  |  | 	s := 0;  // TODO eventually Go will require this to be a uint! | 
					
						
							|  |  |  | 	b := I.ReadByte(); | 
					
						
							|  |  |  | 	for b < 128 { | 
					
						
							|  |  |  | 		x |= int(b) << s; | 
					
						
							|  |  |  | 		s += 7; | 
					
						
							|  |  |  | 		b = I.ReadByte(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// b >= 128 | 
					
						
							|  |  |  | 	x |= ((int(b) - 192) << s); | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print " #", x; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadString() string { | 
					
						
							|  |  |  | 	var buf [256] byte;  // TODO this needs to be fixed | 
					
						
							|  |  |  | 	n := I.ReadInt(); | 
					
						
							|  |  |  | 	for i := 0; i < n; i++ { | 
					
						
							|  |  |  | 		buf[i] = I.ReadByte(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s := string(buf)[0 : n]; | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print ` "`, s, `"`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadObjTag() int { | 
					
						
							|  |  |  | 	tag := I.ReadInt(); | 
					
						
							|  |  |  | 	if tag < 0 { | 
					
						
							|  |  |  | 		panic "tag < 0"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print "\nObj: ", tag;  // obj kind | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tag; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadTypeTag() int { | 
					
						
							|  |  |  | 	tag := I.ReadInt(); | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		if tag > 0 { | 
					
						
							|  |  |  | 			print "\nTyp ", I.ntypes, ": ", tag;  // type form | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			print " [Typ ", -tag, "]";  // type ref | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tag; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadPackageTag() int { | 
					
						
							|  |  |  | 	tag := I.ReadInt(); | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		if tag > 0 { | 
					
						
							|  |  |  | 			print "\nPkg ", I.npkgs, ": ", tag;  // package tag | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			print " [Pkg ", -tag, "]";  // package ref | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tag; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadTypeField() *Globals.Object { | 
					
						
							|  |  |  | 	fld := Globals.NewObject(0, Object.VAR, ""); | 
					
						
							|  |  |  | 	fld.typ = I.ReadType(); | 
					
						
							|  |  |  | 	return fld; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadScope() *Globals.Scope { | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print " {"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scope := Globals.NewScope(nil); | 
					
						
							|  |  |  | 	for n := I.ReadInt(); n > 0; n-- { | 
					
						
							|  |  |  | 		tag := I.ReadObjTag(); | 
					
						
							|  |  |  | 		scope.Insert(I.ReadObject(tag)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print " }"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadObject(tag int) *Globals.Object { | 
					
						
							|  |  |  | 	if tag == Object.PTYPE { | 
					
						
							|  |  |  | 		// primary type object - handled entirely by ReadType() | 
					
						
							|  |  |  | 		typ := I.ReadType(); | 
					
						
							|  |  |  | 		if typ.obj.typ != typ { | 
					
						
							|  |  |  | 			panic "incorrect primary type"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return typ.obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ident := I.ReadString(); | 
					
						
							|  |  |  | 		obj := Globals.NewObject(0, tag, ident); | 
					
						
							|  |  |  | 		obj.typ = I.ReadType(); | 
					
						
							|  |  |  | 		obj.pnolev = I.ReadPackage().obj.pnolev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (tag) { | 
					
						
							|  |  |  | 		default: fallthrough; | 
					
						
							|  |  |  | 		case Object.BAD: fallthrough; | 
					
						
							|  |  |  | 		case Object.PACKAGE: fallthrough; | 
					
						
							|  |  |  | 		case Object.PTYPE: | 
					
						
							|  |  |  | 			panic "UNREACHABLE"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Object.CONST: | 
					
						
							|  |  |  | 			I.ReadInt();  // should set the value field | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Object.TYPE: | 
					
						
							|  |  |  | 			// nothing to do | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Object.VAR: | 
					
						
							|  |  |  | 			I.ReadInt();  // should set the address/offset field | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Object.FUNC: | 
					
						
							|  |  |  | 			I.ReadInt();  // should set the address/offset field | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadType() *Globals.Type { | 
					
						
							|  |  |  | 	tag := I.ReadTypeTag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if tag <= 0 { | 
					
						
							|  |  |  | 		return I.types[-tag];  // type already imported | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	typ := Globals.NewType(tag); | 
					
						
							|  |  |  | 	ptyp := typ;  // primary type | 
					
						
							|  |  |  | 	ident := I.ReadString(); | 
					
						
							|  |  |  | 	if (len(ident) > 0) { | 
					
						
							|  |  |  | 		// primary type | 
					
						
							|  |  |  | 		obj := Globals.NewObject(0, Object.TYPE, ident); | 
					
						
							|  |  |  | 		obj.typ = typ; | 
					
						
							|  |  |  | 		typ.obj = obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// canonicalize type | 
					
						
							|  |  |  | 		pkg := I.ReadPackage(); | 
					
						
							|  |  |  | 		obj.pnolev = pkg.obj.pnolev; | 
					
						
							|  |  |  | 		obj = pkg.scope.InsertImport(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ptyp = obj.typ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	I.types[I.ntypes] = ptyp; | 
					
						
							|  |  |  | 	I.ntypes++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (tag) { | 
					
						
							|  |  |  | 	default: fallthrough; | 
					
						
							|  |  |  | 	case Type.UNDEF: fallthrough; | 
					
						
							|  |  |  | 	case Type.BAD: fallthrough; | 
					
						
							|  |  |  | 	case Type.NIL: fallthrough; | 
					
						
							|  |  |  | 	case Type.BOOL: fallthrough; | 
					
						
							|  |  |  | 	case Type.UINT: fallthrough; | 
					
						
							|  |  |  | 	case Type.INT: fallthrough; | 
					
						
							|  |  |  | 	case Type.FLOAT: fallthrough; | 
					
						
							|  |  |  | 	case Type.STRING: fallthrough; | 
					
						
							|  |  |  | 	case Type.ANY: | 
					
						
							|  |  |  | 		panic "UNREACHABLE"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case Type.ARRAY: | 
					
						
							|  |  |  | 		typ.len_ = I.ReadInt(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.elt = I.ReadType(); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.MAP: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.key = I.ReadType(); | 
					
						
							|  |  |  | 		typ.elt = I.ReadType(); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.CHANNEL: | 
					
						
							|  |  |  | 		typ.flags = I.ReadInt(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.elt = I.ReadType(); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case Type.FUNCTION: | 
					
						
							|  |  |  | 		typ.flags = I.ReadInt(); | 
					
						
							|  |  |  | 		fallthrough; | 
					
						
							|  |  |  | 	case Type.STRUCT: fallthrough; | 
					
						
							|  |  |  | 	case Type.INTERFACE: | 
					
						
							|  |  |  | 		typ.scope = I.ReadScope(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case Type.POINTER: fallthrough; | 
					
						
							|  |  |  | 	case Type.REFERENCE: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.elt = I.ReadType(); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ptyp;  // only use primary type | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (I *Importer) ReadPackage() *Globals.Package { | 
					
						
							|  |  |  | 	tag := I.ReadPackageTag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tag <= 0) { | 
					
						
							|  |  |  | 		return I.pkgs[-tag];  // package already imported | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ident := I.ReadString(); | 
					
						
							|  |  |  | 	file_name := I.ReadString(); | 
					
						
							|  |  |  | 	key := I.ReadString(); | 
					
						
							|  |  |  | 	pkg := I.comp.Lookup(file_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if pkg == nil { | 
					
						
							|  |  |  | 		// new package | 
					
						
							|  |  |  | 		pkg = Globals.NewPackage(file_name); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		pkg.obj = Globals.NewObject(-1, Object.PACKAGE, ident); | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 		pkg.scope = Globals.NewScope(nil); | 
					
						
							|  |  |  | 		pkg = I.comp.InsertImport(pkg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (key != pkg.key) { | 
					
						
							|  |  |  | 		// package inconsistency | 
					
						
							|  |  |  | 		panic "package key inconsistency"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	I.pkgs[I.npkgs] = pkg; | 
					
						
							|  |  |  | 	I.npkgs++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pkg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.Package { | 
					
						
							|  |  |  | 	I.comp = comp; | 
					
						
							|  |  |  | 	I.debug = false; | 
					
						
							|  |  |  | 	I.buf = ""; | 
					
						
							|  |  |  | 	I.pos = 0; | 
					
						
							|  |  |  | 	I.npkgs = 0; | 
					
						
							|  |  |  | 	I.ntypes = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	if I.debug { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		print "importing from ", file_name, "\n"; | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	buf, ok := sys.readfile(file_name); | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		return nil; | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	I.buf = buf; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	// Predeclared types are "pre-imported". | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | 	for p := Universe.types.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		if p.typ.ref != I.ntypes { | 
					
						
							|  |  |  | 			panic "incorrect ref for predeclared type"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		I.types[I.ntypes] = p.typ; | 
					
						
							|  |  |  | 		I.ntypes++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pkg := I.ReadPackage(); | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		tag := I.ReadObjTag(); | 
					
						
							|  |  |  | 		if tag == 0 { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		obj := I.ReadObject(tag); | 
					
						
							|  |  |  | 		obj.pnolev = pkg.obj.pnolev; | 
					
						
							|  |  |  | 		pkg.scope.InsertImport(obj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if I.debug { | 
					
						
							|  |  |  | 		print "\n(", I.pos, " bytes)\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return pkg; | 
					
						
							| 
									
										
										
										
											2008-07-18 14:04:21 -07:00
										 |  |  | } |