| 
									
										
										
										
											2008-07-30 21:51:25 -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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Verifies compiler-internal data structures. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package Verifier | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Utils "utils" | 
					
						
							|  |  |  | import Scanner "scanner" | 
					
						
							|  |  |  | import Globals "globals" | 
					
						
							|  |  |  | import Object "object" | 
					
						
							|  |  |  | import Type "type" | 
					
						
							|  |  |  | import Universe "universe" | 
					
						
							|  |  |  | import Import "import" | 
					
						
							|  |  |  | import AST "ast" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func Error(msg string) { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 	panic("internal compiler error: ", msg, "\n"); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | type Verifier struct { | 
					
						
							|  |  |  | 	comp *Globals.Compilation; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// various sets for marking the graph (and thus avoid cycles) | 
					
						
							|  |  |  | 	objs *map[*Globals.Object] bool; | 
					
						
							|  |  |  | 	typs *map[*Globals.Type] bool; | 
					
						
							|  |  |  | 	pkgs *map[*Globals.Package] bool; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | func (V *Verifier) VerifyType(typ *Globals.Type) { | 
					
						
							| 
									
										
										
										
											2008-09-12 12:09:43 -07:00
										 |  |  | 	if present, ok := V.typs[typ]; present { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		return;  // already verified | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	V.typs[typ] = true; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	if typ.obj != nil { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		V.VerifyObject(typ.obj, 0); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	switch typ.form { | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	case Type.VOID: | 
					
						
							|  |  |  | 		break;  // TODO for now - remove eventually | 
					
						
							|  |  |  | 	case Type.FORWARD: | 
					
						
							|  |  |  | 		if typ.scope == nil { | 
					
						
							|  |  |  | 			Error("forward types must have a scope"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.NIL: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.BOOL: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.UINT: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.INT: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.FLOAT: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.STRING: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.ANY: | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2008-07-31 10:47:10 -07:00
										 |  |  | 	case Type.ALIAS: | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	case Type.ARRAY: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.STRUCT: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.INTERFACE: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.MAP: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.CHANNEL: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.FUNCTION: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.POINTER: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Type.REFERENCE: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		Error("illegal type form " + Type.FormStr(typ.form)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int) { | 
					
						
							| 
									
										
										
										
											2008-09-12 12:09:43 -07:00
										 |  |  | 	if present, ok := V.objs[obj]; present { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		return;  // already verified | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	V.objs[obj] = true; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// all objects have a non-nil type | 
					
						
							|  |  |  | 	V.VerifyType(obj.typ); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	switch obj.kind { | 
					
						
							|  |  |  | 	case Object.CONST: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Object.TYPE: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Object.VAR: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Object.FUNC: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Object.PACKAGE: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Object.LABEL: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		Error("illegal object kind " + Object.KindStr(obj.kind)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | func (V *Verifier) VerifyScope(scope *Globals.Scope) { | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	for p := scope.entries.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		V.VerifyObject(p.obj, 0); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | func (V *Verifier) VerifyPackage(pkg *Globals.Package, pno int) { | 
					
						
							| 
									
										
										
										
											2008-09-12 12:09:43 -07:00
										 |  |  | 	if present, ok := V.pkgs[pkg]; present { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		return;  // already verified | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	V.pkgs[pkg] = true; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	V.VerifyObject(pkg.obj, pno); | 
					
						
							|  |  |  | 	V.VerifyScope(pkg.scope); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | func (V *Verifier) Verify(comp *Globals.Compilation) { | 
					
						
							|  |  |  | 	// initialize Verifier | 
					
						
							|  |  |  | 	V.comp = comp; | 
					
						
							|  |  |  | 	V.objs = new(map[*Globals.Object] bool); | 
					
						
							|  |  |  | 	V.typs = new(map[*Globals.Type] bool); | 
					
						
							|  |  |  | 	V.pkgs = new(map[*Globals.Package] bool); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// verify all packages | 
					
						
							|  |  |  | 	filenames := new(map[string] bool); | 
					
						
							| 
									
										
										
										
											2008-08-04 10:19:36 -07:00
										 |  |  | 	for i := 0; i < comp.pkg_ref; i++ { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		pkg := comp.pkg_list[i]; | 
					
						
							|  |  |  | 		// each pkg filename must appear only once | 
					
						
							| 
									
										
										
										
											2008-09-12 12:09:43 -07:00
										 |  |  | 		if present, ok := filenames[pkg.file_name]; present { | 
					
						
							|  |  |  | 			Error("package filename present more than once"); | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		filenames[pkg.file_name] = true; | 
					
						
							|  |  |  | 		V.VerifyPackage(pkg, i); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:51:25 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export func Verify(comp *Globals.Compilation) { | 
					
						
							|  |  |  | 	V := new(Verifier); | 
					
						
							|  |  |  | 	V.Verify(comp); | 
					
						
							|  |  |  | } |