Commit b8635907 authored by Robert Griesemer's avatar Robert Griesemer

Snapshot.

Preparations to track identifiers and declarations so that we can
generate good html links as pretty printer output:
- brought over old code and adjusted it
- initial hookups, nothing really running yet

R=r
OCL=21383
CL=21383
parent e53d5ad6
......@@ -23,11 +23,11 @@ install: pretty
cp pretty $(HOME)/bin/pretty
clean:
rm -f pretty *.6 *~
rm -f pretty *.6 *.a *~
pretty.6: platform.6 printer.6 compilation.6
compilation.6: platform.6 scanner.6 parser.6 ast.6
compilation.6: platform.6 scanner.6 parser.6 ast.6 typechecker.6
ast.6: scanner.6
......@@ -39,5 +39,13 @@ platform.6: utils.6
printer.6: scanner.6 ast.6
typechecker.6: ast.6 universe.6 globals.6 type.6
universe.6: globals.6 object.6 type.6
object.6: globals.6
type.6: globals.6 object.6
%.6: %.go
$(G) $(F) $<
......@@ -10,6 +10,7 @@ import Platform "platform"
import Scanner "scanner"
import Parser "parser"
import AST "ast"
import TypeChecker "typechecker"
func assert(b bool) {
......@@ -133,6 +134,11 @@ export func Compile(src_file string, flags *Flags) (*AST.Program, int) {
parser.Open(flags.verbose, flags.sixg, flags.deps, &scanner, tstream);
prog := parser.ParseProgram();
if err.nerrors == 0 {
TypeChecker.CheckProgram(prog);
}
return prog, err.nerrors;
}
......
// 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 Globals
// The following types should really be in their respective files
// (object.go, type.go, scope.go, package.go, compilation.go, etc.) but
// they refer to each other and we don't know how to handle forward
// declared pointers across packages yet.
// ----------------------------------------------------------------------------
type Type struct
type Scope struct
type Elem struct
type OldCompilation struct
// Object represents a language object, such as a constant, variable, type,
// etc. (kind). An objects is (pre-)declared at a particular position in the
// source code (pos), has a name (ident), a type (typ), and a package number
// or nesting level (pnolev).
export type Object struct {
exported bool;
pos int; // source position (< 0 if unknown position)
kind int;
ident string;
typ *Type; // nil for packages
pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
}
export type Type struct {
ref int; // for exporting only: >= 0 means already exported
form int;
size int; // in bytes
len int; // array length, no. of function/method parameters (w/o recv)
aux int; // channel info
obj *Object; // primary type object or NULL
key *Type; // alias base type or map key
elt *Type; // aliased type, array, map, channel or pointer element type, function result type, tuple function type
scope *Scope; // forwards, structs, interfaces, functions
}
export type Package struct {
ref int; // for exporting only: >= 0 means already exported
file_name string;
key string;
obj *Object;
scope *Scope; // holds the (global) objects in this package
}
export type Scope struct {
parent *Scope;
entries *map[string] *Object;
}
export type Environment struct {
Error *(comp *OldCompilation, pos int, msg string);
Import *(comp *OldCompilation, pkg_file string) *Package;
Export *(comp *OldCompilation, pkg_file string);
Compile *(comp *OldCompilation, src_file string);
}
export type OldCompilation struct {
// environment
env *Environment;
// TODO rethink the need for this here
src_file string;
src string;
// Error handling
nerrors int; // number of errors reported
errpos int; // last error position
// TODO use open arrays eventually
pkg_list [256] *Package; // pkg_list[0] is the current package
pkg_ref int;
}
export type Expr interface {
op() int; // node operation
pos() int; // source position
typ() *Type;
// ... more to come here
}
export type Stat interface {
// ... more to come here
}
// TODO This is hideous! We need to have a decent way to do lists.
// Ideally open arrays that allow '+'.
export type Elem struct {
next *Elem;
val int;
str string;
obj *Object;
typ *Type;
expr Expr
}
// ----------------------------------------------------------------------------
// Creation
export var Universe_void_typ *Type // initialized by Universe to Universe.void_typ
export func NewObject(pos, kind int, ident string) *Object {
obj := new(Object);
obj.exported = false;
obj.pos = pos;
obj.kind = kind;
obj.ident = ident;
obj.typ = Universe_void_typ;
obj.pnolev = 0;
return obj;
}
export func NewType(form int) *Type {
typ := new(Type);
typ.ref = -1; // not yet exported
typ.form = form;
return typ;
}
export func NewPackage(file_name string, obj *Object, scope *Scope) *Package {
pkg := new(Package);
pkg.ref = -1; // not yet exported
pkg.file_name = file_name;
pkg.key = "<the package key>"; // empty key means package forward declaration
pkg.obj = obj;
pkg.scope = scope;
return pkg;
}
export func NewScope(parent *Scope) *Scope {
scope := new(Scope);
scope.parent = parent;
scope.entries = new(map[string]*Object, 8);
return scope;
}
// ----------------------------------------------------------------------------
// Object methods
func (obj *Object) Copy() *Object {
copy := new(Object);
copy.exported = obj.exported;
copy.pos = obj.pos;
copy.kind = obj.kind;
copy.ident = obj.ident;
copy.typ = obj.typ;
copy.pnolev = obj.pnolev;
return copy;
}
// ----------------------------------------------------------------------------
// Scope methods
func (scope *Scope) Lookup(ident string) *Object {
obj, found := scope.entries[ident];
if found {
return obj;
}
return nil;
}
func (scope *Scope) Add(obj* Object) {
scope.entries[obj.ident] = obj;
}
func (scope *Scope) Insert(obj *Object) {
if scope.Lookup(obj.ident) != nil {
panic("obj already inserted");
}
scope.Add(obj);
}
func (scope *Scope) InsertImport(obj *Object) *Object {
p := scope.Lookup(obj.ident);
if p == nil {
scope.Add(obj);
p = obj;
}
return p;
}
func (scope *Scope) Print() {
print("scope {");
for key := range scope.entries {
print("\n ", key);
}
print("\n}\n");
}
// ----------------------------------------------------------------------------
// Compilation methods
func (C *OldCompilation) Lookup(file_name string) *Package {
for i := 0; i < C.pkg_ref; i++ {
pkg := C.pkg_list[i];
if pkg.file_name == file_name {
return pkg;
}
}
return nil;
}
func (C *OldCompilation) Insert(pkg *Package) {
if C.Lookup(pkg.file_name) != nil {
panic("package already inserted");
}
pkg.obj.pnolev = C.pkg_ref;
C.pkg_list[C.pkg_ref] = pkg;
C.pkg_ref++;
}
// 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 Object
import Globals "globals"
export const /* kind */ (
BAD = iota; // error handling
CONST; TYPE; VAR; FIELD; FUNC; BUILTIN; PACKAGE; LABEL;
END; // end of scope (import/export only)
)
// The 'Object' declaration should be here as well, but 6g cannot handle
// this due to cross-package circular references. For now it's all in
// globals.go.
export func KindStr(kind int) string {
switch kind {
case BAD: return "BAD";
case CONST: return "CONST";
case TYPE: return "TYPE";
case VAR: return "VAR";
case FIELD: return "FIELD";
case FUNC: return "FUNC";
case BUILTIN: return "BUILTIN";
case PACKAGE: return "PACKAGE";
case LABEL: return "LABEL";
case END: return "END";
}
return "<unknown Object kind>";
}
// 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 Type
import Globals "globals"
import Object "object"
export const /* form */ (
// internal types
// We should never see one of these.
UNDEF = iota;
// VOID types are used when we don't have a type. Never exported.
// (exported type forms must be > 0)
VOID;
// BAD types are compatible with any type and don't cause further errors.
// They are introduced only as a result of an error in the source code. A
// correct program cannot have BAD types.
BAD;
// FORWARD types are forward-declared (incomplete) types. They can only
// be used as element types of pointer types and must be resolved before
// their internals are accessible.
FORWARD;
// TUPLE types represent multi-valued result types of functions and
// methods.
TUPLE;
// The type of nil.
NIL;
// basic types
BOOL; UINT; INT; FLOAT; STRING; INTEGER;
// 'any' type // TODO this should go away eventually
ANY;
// composite types
ALIAS; ARRAY; STRUCT; INTERFACE; MAP; CHANNEL; FUNCTION; METHOD; POINTER;
)
export const /* Type.aux */ (
SEND = 1; // chan>
RECV = 2; // chan<
)
// The 'Type' declaration should be here as well, but 6g cannot handle
// this due to cross-package circular references. For now it's all in
// globals.go.
export func FormStr(form int) string {
switch form {
case VOID: return "VOID";
case BAD: return "BAD";
case FORWARD: return "FORWARD";
case TUPLE: return "TUPLE";
case NIL: return "NIL";
case BOOL: return "BOOL";
case UINT: return "UINT";
case INT: return "INT";
case FLOAT: return "FLOAT";
case STRING: return "STRING";
case ANY: return "ANY";
case ALIAS: return "ALIAS";
case ARRAY: return "ARRAY";
case STRUCT: return "STRUCT";
case INTERFACE: return "INTERFACE";
case MAP: return "MAP";
case CHANNEL: return "CHANNEL";
case FUNCTION: return "FUNCTION";
case METHOD: return "METHOD";
case POINTER: return "POINTER";
}
return "<unknown Type form>";
}
export func Equal(x, y *Globals.Type) bool;
func Equal0(x, y *Globals.Type) bool {
if x == y {
return true; // identical types are equal
}
if x.form == BAD || y.form == BAD {
return true; // bad types are always equal (avoid excess error messages)
}
// TODO where to check for *T == nil ?
if x.form != y.form {
return false; // types of different forms are not equal
}
switch x.form {
case FORWARD, BAD:
break;
case NIL, BOOL, STRING, ANY:
return true;
case UINT, INT, FLOAT:
return x.size == y.size;
case ARRAY:
return
x.len == y.len &&
Equal(x.elt, y.elt);
case MAP:
return
Equal(x.key, y.key) &&
Equal(x.elt, y.elt);
case CHANNEL:
return
x.aux == y.aux &&
Equal(x.elt, y.elt);
case FUNCTION, METHOD:
{ panic();
/*
xp := x.scope.entries;
yp := x.scope.entries;
if x.len != y.len && // number of parameters
xp.len != yp.len // recv + parameters + results
{
return false;
}
for p, q := xp.first, yp.first; p != nil; p, q = p.next, q.next {
xf := p.obj;
yf := q.obj;
if xf.kind != Object.VAR || yf.kind != Object.VAR {
panic("parameters must be vars");
}
if !Equal(xf.typ, yf.typ) {
return false;
}
}
*/
}
return true;
case STRUCT:
/*
{ ObjList* xl = &x.scope.list;
ObjList* yl = &y.scope.list;
if xl.len() != yl.len() {
return false; // scopes of different sizes are not equal
}
for int i = xl.len(); i-- > 0; {
Object* xf = (*xl)[i];
Object* yf = (*yl)[i];
ASSERT(xf.kind == Object.VAR && yf.kind == Object.VAR);
if xf.name != yf.name) || ! EqualTypes(xf.type(), yf.type() {
return false;
}
}
}
return true;
*/
// Scopes must be identical for them to be equal.
// If we reach here, they weren't.
return false;
case INTERFACE:
panic("UNIMPLEMENTED");
return false;
case POINTER:
return Equal(x.elt, y.elt);
case TUPLE:
panic("UNIMPLEMENTED");
return false;
}
panic("UNREACHABLE");
return false;
}
export func Equal(x, y *Globals.Type) bool {
res := Equal0(x, y);
// TODO should do the check below only in debug mode
if Equal0(y, x) != res {
panic("type equality must be symmetric");
}
return res;
}
export func Assigneable(from, to *Globals.Type) bool {
if Equal(from, to) {
return true;
}
panic("UNIMPLEMENTED");
return false;
}
// 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 Universe
import (
"array"
Globals "globals";
Object "object";
Type "type";
)
export var (
scope *Globals.Scope;
types array.Array;
// internal types
void_typ,
bad_typ,
nil_typ,
// basic types
bool_typ,
uint8_typ,
uint16_typ,
uint32_typ,
uint64_typ,
int8_typ,
int16_typ,
int32_typ,
int64_typ,
float32_typ,
float64_typ,
float80_typ,
string_typ,
integer_typ,
// convenience types
byte_typ,
uint_typ,
int_typ,
float_typ,
uintptr_typ *Globals.Type;
true_obj,
false_obj,
iota_obj,
nil_obj *Globals.Object;
)
func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object {
obj := Globals.NewObject(-1 /* no source pos */, kind, ident);
obj.typ = typ;
if kind == Object.TYPE && typ.obj == nil {
typ.obj = obj; // set primary type object
}
scope.Insert(obj);
return obj
}
func DeclType(form int, ident string, size int) *Globals.Type {
typ := Globals.NewType(form);
typ.size = size;
return DeclObj(Object.TYPE, ident, typ).typ;
}
func Register(typ *Globals.Type) *Globals.Type {
typ.ref = types.Len();
types.Push(typ);
return typ;
}
func init() {
scope = Globals.NewScope(nil); // universe has no parent
types.Init(32);
// Interal types
void_typ = Globals.NewType(Type.VOID);
Globals.Universe_void_typ = void_typ;
bad_typ = Globals.NewType(Type.BAD);
nil_typ = Globals.NewType(Type.NIL);
// Basic types
bool_typ = Register(DeclType(Type.BOOL, "bool", 1));
uint8_typ = Register(DeclType(Type.UINT, "uint8", 1));
uint16_typ = Register(DeclType(Type.UINT, "uint16", 2));
uint32_typ = Register(DeclType(Type.UINT, "uint32", 4));
uint64_typ = Register(DeclType(Type.UINT, "uint64", 8));
int8_typ = Register(DeclType(Type.INT, "int8", 1));
int16_typ = Register(DeclType(Type.INT, "int16", 2));
int32_typ = Register(DeclType(Type.INT, "int32", 4));
int64_typ = Register(DeclType(Type.INT, "int64", 8));
float32_typ = Register(DeclType(Type.FLOAT, "float32", 4));
float64_typ = Register(DeclType(Type.FLOAT, "float64", 8));
float80_typ = Register(DeclType(Type.FLOAT, "float80", 10));
string_typ = Register(DeclType(Type.STRING, "string", 8));
integer_typ = Register(DeclType(Type.INTEGER, "integer", 8));
// All but 'byte' should be platform-dependent, eventually.
byte_typ = Register(DeclType(Type.UINT, "byte", 1));
uint_typ = Register(DeclType(Type.UINT, "uint", 4));
int_typ = Register(DeclType(Type.INT, "int", 4));
float_typ = Register(DeclType(Type.FLOAT, "float", 4));
uintptr_typ = Register(DeclType(Type.UINT, "uintptr", 8));
// Predeclared constants
true_obj = DeclObj(Object.CONST, "true", bool_typ);
false_obj = DeclObj(Object.CONST, "false", bool_typ);
iota_obj = DeclObj(Object.CONST, "iota", int_typ);
nil_obj = DeclObj(Object.CONST, "nil", nil_typ);
// Builtin functions
DeclObj(Object.BUILTIN, "len", void_typ);
DeclObj(Object.BUILTIN, "new", void_typ);
DeclObj(Object.BUILTIN, "panic", void_typ);
DeclObj(Object.BUILTIN, "print", void_typ);
// scope.Print();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment