2008-07-30 22:51:25 -06: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 22:20:42 -06:00
|
|
|
panic("internal compiler error: ", msg, "\n");
|
2008-07-30 22:51:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-05 16:20:58 -06: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 22:51:25 -06:00
|
|
|
|
|
|
|
|
2008-08-05 16:20:58 -06:00
|
|
|
func (V *Verifier) VerifyType(typ *Globals.Type) {
|
2008-09-12 13:09:43 -06:00
|
|
|
if present, ok := V.typs[typ]; present {
|
2008-08-05 16:20:58 -06:00
|
|
|
return; // already verified
|
|
|
|
}
|
|
|
|
V.typs[typ] = true;
|
|
|
|
|
2008-07-30 22:51:25 -06:00
|
|
|
if typ.obj != nil {
|
2008-08-05 16:20:58 -06:00
|
|
|
V.VerifyObject(typ.obj, 0);
|
2008-07-30 22:51:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
switch typ.form {
|
2008-08-11 10:45:40 -06: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 22:51:25 -06: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 11:47:10 -06:00
|
|
|
case Type.ALIAS:
|
|
|
|
break;
|
2008-07-30 22:51:25 -06: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 16:20:58 -06:00
|
|
|
func (V *Verifier) VerifyObject(obj *Globals.Object, pnolev int) {
|
2008-09-12 13:09:43 -06:00
|
|
|
if present, ok := V.objs[obj]; present {
|
2008-08-05 16:20:58 -06:00
|
|
|
return; // already verified
|
|
|
|
}
|
|
|
|
V.objs[obj] = true;
|
|
|
|
|
|
|
|
// all objects have a non-nil type
|
|
|
|
V.VerifyType(obj.typ);
|
2008-07-30 22:51:25 -06: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 16:20:58 -06:00
|
|
|
func (V *Verifier) VerifyScope(scope *Globals.Scope) {
|
2008-07-30 22:51:25 -06:00
|
|
|
for p := scope.entries.first; p != nil; p = p.next {
|
2008-08-05 16:20:58 -06:00
|
|
|
V.VerifyObject(p.obj, 0);
|
2008-07-30 22:51:25 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-05 16:20:58 -06:00
|
|
|
func (V *Verifier) VerifyPackage(pkg *Globals.Package, pno int) {
|
2008-09-12 13:09:43 -06:00
|
|
|
if present, ok := V.pkgs[pkg]; present {
|
2008-08-05 16:20:58 -06:00
|
|
|
return; // already verified
|
|
|
|
}
|
|
|
|
V.pkgs[pkg] = true;
|
|
|
|
|
|
|
|
V.VerifyObject(pkg.obj, pno);
|
|
|
|
V.VerifyScope(pkg.scope);
|
2008-07-30 22:51:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-05 16:20:58 -06: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 11:19:36 -06:00
|
|
|
for i := 0; i < comp.pkg_ref; i++ {
|
2008-08-05 16:20:58 -06:00
|
|
|
pkg := comp.pkg_list[i];
|
|
|
|
// each pkg filename must appear only once
|
2008-09-12 13:09:43 -06:00
|
|
|
if present, ok := filenames[pkg.file_name]; present {
|
|
|
|
Error("package filename present more than once");
|
2008-08-05 16:20:58 -06:00
|
|
|
}
|
|
|
|
filenames[pkg.file_name] = true;
|
|
|
|
V.VerifyPackage(pkg, i);
|
2008-07-30 22:51:25 -06:00
|
|
|
}
|
|
|
|
}
|
2008-08-05 16:20:58 -06:00
|
|
|
|
|
|
|
|
|
|
|
export func Verify(comp *Globals.Compilation) {
|
|
|
|
V := new(Verifier);
|
|
|
|
V.Verify(comp);
|
|
|
|
}
|