Commit 699721a0 authored by Robert Griesemer's avatar Robert Griesemer

- removed obsolete files from repository

(most of this has been integrated into pretty,
the rest has been archived).

R=r
OCL=23842
CL=23842
parent eecce5f1
// 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 AST
import Globals "globals"
import GlobalObject "object"
import Type "type"
import Universe "universe"
// ----------------------------------------------------------------------------
// Expressions
const /* op */ (
LITERAL = iota;
OBJECT;
DEREF;
SELECT;
CALL;
TUPLE;
)
// ----------------------------------------------------------------------------
// Literals
type Literal struct {
pos_ int;
typ_ *Globals.Type;
b bool;
i int;
f float;
s string;
}
func (x *Literal) op() int { return LITERAL; }
func (x *Literal) pos() int { return x.pos_; }
func (x *Literal) typ() *Globals.Type { return x.typ_; }
func NewLiteral(pos int, typ *Globals.Type) *Literal {
x := new(Literal);
x.pos_ = pos;
x.typ_ = typ;
return x;
}
var Bad, True, False, Nil *Literal;
// ----------------------------------------------------------------------------
// Objects
// NOTE We could use Globals.Object directly if we'd added a typ()
// method to its interface. However, this would require renaming the
// typ field everywhere... - Need to think about accessors again.
type Object struct {
pos_ int;
obj *Globals.Object;
}
func (x *Object) op() int { return OBJECT; }
func (x *Object) pos() int { return x.pos_; }
func (x *Object) typ() *Globals.Type { return x.obj.typ; }
func NewObject(pos int, obj* Globals.Object) *Object {
x := new(Object);
x.pos_ = pos;
x.obj = obj;
return x;
}
// ----------------------------------------------------------------------------
// Derefs
// TODO model Deref as unary operation?
type Deref struct {
ptr_ Globals.Expr;
}
func (x *Deref) op() int { return DEREF; }
func (x *Deref) pos() int { return x.ptr_.pos(); }
func (x *Deref) typ() *Globals.Type { return x.ptr_.typ().elt; }
func NewDeref(ptr Globals.Expr) *Deref {
x := new(Deref);
x.ptr_ = ptr;
return x;
}
// ----------------------------------------------------------------------------
// Selectors
// TODO model Selector as binary operation?
type Selector struct {
pos_ int;
typ_ *Globals.Type;
}
func (x *Selector) op() int { return SELECT; }
func (x *Selector) pos() int { return x.pos_; }
func (x *Selector) typ() *Globals.Type { return x.typ_; }
func NewSelector(pos int, typ *Globals.Type) *Selector {
x := new(Selector);
x.pos_ = pos;
x.typ_ = typ;
return x;
}
// ----------------------------------------------------------------------------
// Calls
type Call struct {
recv, callee Globals.Expr;
args *Globals.List;
}
func (x *Call) op() int { return CALL; }
func (x *Call) pos() int { return 0; }
func (x *Call) typ() *Globals.Type { return nil; }
func NewCall(args *Globals.List) *Call {
x := new(Call);
x.args = args;
return x;
}
// ----------------------------------------------------------------------------
// Binary expressions
type BinaryExpr struct {
op_ int;
pos_ int;
typ_ *Globals.Type;
x, y Globals.Expr;
}
func (x *BinaryExpr) op() int { return x.op_; }
func (x *BinaryExpr) pos() int { return x.pos_; }
func (x *BinaryExpr) typ() *Globals.Type { return x.typ_; }
// ----------------------------------------------------------------------------
// Tuples
type Tuple struct {
typ_ *Globals.Type;
list *Globals.List;
}
func (x *Tuple) op() int { return TUPLE; }
func (x *Tuple) pos() int { return x.list.first.expr.pos(); }
func (x *Tuple) typ() *Globals.Type { return x.typ_; }
func NewTuple(list *Globals.List) *Tuple {
// make corresponding tuple type
scope := Globals.NewScope(nil);
for p := list.first; p != nil; p = p.next {
x := p.expr;
obj := Globals.NewObject(x.pos(), GlobalObject.FIELD, "");
obj.typ = x.typ();
scope.Add(obj);
}
typ := Globals.NewType(Type.TUPLE);
typ.scope = scope;
// create the tuple
x := new(Tuple);
x.typ_ = typ;
x.list = list;
return x;
}
// ----------------------------------------------------------------------------
// Statements
type Block struct {
// TODO fill in
}
type IfStat struct {
cond Globals.Expr;
then_ Globals.Stat;
else_ Globals.Stat;
}
// ----------------------------------------------------------------------------
// Initialization
func init() {
Bad = NewLiteral(-1, Universe.bad_t);
True = NewLiteral(-1, Universe.bool_t); True.b = true;
False = NewLiteral(-1, Universe.bool_t); False.b = false;
Nil = NewLiteral(-1, Universe.nil_t);
}
// 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.
// Base for the decls.go tests.
package base
type Foo int
type Bar *float;
type Node struct {
left, right *Node;
val bool;
f Foo;
}
func (p *Node) F(x int) {};
type I interface {
f();
}
// 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 Compilation
import Platform "platform"
import Utils "utils"
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
import Scanner "scanner"
import AST "ast"
import Parser "parser"
import Importer "import"
import Exporter "export"
import Printer "printer"
import Verifier "verifier"
// Compute (line, column) information for a given source position.
func LineCol(src string, pos int) (line, col int) {
line = 1;
lpos := 0;
if pos > len(src) {
pos = len(src);
}
for i := 0; i < pos; i++ {
if src[i] == '\n' {
line++;
lpos = i;
}
}
return line, pos - lpos;
}
func Error(comp *Globals.Compilation, pos int, msg string) {
const errdist = 10;
delta := pos - comp.errpos; // may be negative!
if delta < 0 {
delta = -delta;
}
if delta > errdist || comp.nerrors == 0 /* always report first error */ {
print(comp.src_file);
if pos >= 0 {
// print position
line, col := LineCol(comp.src, pos);
if Platform.USER == "gri" {
print(":", line, ":", col);
} else {
print(":", line);
}
}
print(": ", msg, "\n");
comp.nerrors++;
comp.errpos = pos;
}
if comp.nerrors >= 10 {
sys.Exit(1);
}
}
func ReadImport(comp* Globals.Compilation, filename string, update bool) (data string, ok bool) {
if filename == "" {
panic("illegal package file name");
}
// see if it just works
data, ok = Platform.ReadObjectFile(filename);
if ok {
return data, ok;
}
if filename[0] == '/' {
// absolute path
panic(`don't know how to handle absolute import file path "` + filename + `"`);
}
// relative path
// try relative to the $GOROOT/pkg directory
std_filename := Platform.GOROOT + "/pkg/" + filename;
data, ok = Platform.ReadObjectFile(std_filename);
if ok {
return data, ok;
}
if !update {
return "", false;
}
// TODO BIG HACK - fix this!
// look for a src file
// see if it just works
data, ok = Platform.ReadSourceFile(filename);
if ok {
comp.env.Compile(comp, filename + Platform.src_file_ext);
data, ok = ReadImport(comp, filename, false);
if ok {
return data, ok;
}
}
return "", false;
}
func Import(comp *Globals.Compilation, pkg_file string) *Globals.Package {
data, ok := ReadImport(comp, pkg_file, comp.flags.update_packages);
var pkg *Globals.Package;
if ok {
pkg = Importer.Import(comp, data);
}
return pkg;
}
func Export(comp *Globals.Compilation, pkg_file string) {
data := Exporter.Export(comp);
ok := Platform.WriteObjectFile(pkg_file, data);
if !ok {
panic("export failed");
}
}
func Compile(comp *Globals.Compilation, src_file string) {
// TODO This is incorrect: When compiling with the -r flag, we are
// calling this function recursively w/o setting up a new comp - this
// is broken and leads to an assertion error (more then one package
// upon parsing of the package header).
src, ok := Platform.ReadSourceFile(src_file);
if !ok {
print("cannot open ", src_file, "\n");
return;
}
comp.src_file = src_file;
comp.src = src;
if comp.flags.verbosity > 0 {
print(src_file, "\n");
}
scanner := new(Scanner.Scanner);
scanner.Open(src_file, src);
var tstream chan *Scanner.Token;
if comp.flags.token_chan {
tstream = make(chan *Scanner.Token, 100);
go scanner.Server(tstream);
}
parser := new(Parser.Parser);
parser.Open(comp, scanner, tstream);
parser.ParseProgram();
if parser.scanner.nerrors > 0 {
return;
}
Verifier.Verify(comp);
if comp.flags.print_interface {
Printer.PrintObject(comp, comp.pkg_list[0].obj, false);
}
Export(comp, src_file);
}
// 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.
// Tests.
package decls
import "base"
import base2 "base"
const c0 int = 0
const c1 float = 1.
const (
c2 byte = 2;
c3 int = 3;
c4 float = 4.;
)
type (
Node0 base.Node
Node1 *base2.Node
)
type T0 byte
type T1 T0
type (
T2 [10]T0;
T3 map [string] int;
)
type T4 struct {
f1, f2, f3 int;
f4 [] float;
};
type (
T5 *T4;
)
type F0 ()
type F1 (a int)
type F2 (a, b int, c float)
type F3 () bool
type F4 (a int) (z T5, ok bool)
type F5 (a, b int, c float) (z T5, ok bool)
type F6 (a int, b float) bool
type F7 (a int, b float, c, d *bool) bool
type T6 chan int
type T7 <- chan *T6
type T8 chan <- *T6
type T9 struct {
p *T9;
q [] map [int] *T9;
f *(x, y *T9) *T9;
}
type T11 struct {
p *T10;
}
type T10 struct {
p *T11;
}
type T12 struct {
p *T12
}
type I0 interface {}
type I1 interface {
Do0(q *I0);
Do1(p *I1) bool;
}
type I2 interface {
M0();
M1(a int);
M2(a, b int, c float);
M3() bool;
M4(a int) (z T5, ok bool);
M5(a, b int, c float) (z T5, ok bool);
}
var v0 int
var v1 float = c1
var (
v2 T2;
v3 struct {
f1, f2, f3 *M0;
}
)
func f0() {}
func f1(a int) {}
func f2(a, b int, c float) {}
func f3() bool { return false; }
func f4(a int) (z T5, ok bool) {}
func f5(a, b int, c float) (z T5, ok bool) {
u, v := 0, 0;
return;
}
func (p *T4) m0() {}
func (p *T4) m1(a int) {}
func (p *T4) m2(a, b int, c float) {}
func (p *T4) m3() bool { return false; }
func (p *T4) m4(a int) (z T5, ok bool) { return; }
func (p *T4) m5(a, b int, c float) (z T5, ok bool) {
L: var x = a;
}
func f2() {
type T *T14;
}
type T14 int;
// 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 Platform "platform"
import Utils "utils"
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
type Exporter struct {
comp *Globals.Compilation;
debug bool;
buf [4*1024] byte;
buf_pos int;
pkg_ref int;
type_ref int;
};
func (E *Exporter) WriteObject(obj *Globals.Object);
func (E *Exporter) WriteByte(x byte) {
E.buf[E.buf_pos] = x;
E.buf_pos++;
/*
if E.debug {
print(" ", x);
}
*/
}
func (E *Exporter) WriteInt(x int) {
x0 := x;
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));
/*
if E.debug {
print(" #", x0);
}
*/
}
func (E *Exporter) WriteString(s string) {
n := len(s);
E.WriteInt(n);
for i := 0; i < n; i++ {
E.WriteByte(s[i]);
}
if E.debug {
print(` "`, s, `"`);
}
}
func (E *Exporter) WritePackageTag(tag int) {
E.WriteInt(tag);
if E.debug {
if tag >= 0 {
print(" [P", tag, "]"); // package ref
} else {
print("\nP", E.pkg_ref, ":");
}
}
}
func (E *Exporter) WriteTypeTag(tag int) {
E.WriteInt(tag);
if E.debug {
if tag >= 0 {
print(" [T", tag, "]"); // type ref
} else {
print("\nT", E.type_ref, ": ", Type.FormStr(-tag));
}
}
}
func (E *Exporter) WriteObjectTag(tag int) {
if tag < 0 {
panic("tag < 0");
}
E.WriteInt(tag);
if E.debug {
print("\n", Object.KindStr(tag));
}
}
func (E *Exporter) WritePackage(pkg *Globals.Package) {
if E.comp.pkg_list[pkg.obj.pnolev] != pkg {
panic("inconsistent package object");
}
if pkg.ref >= 0 {
E.WritePackageTag(pkg.ref); // package already exported
return;
}
E.WritePackageTag(-1);
pkg.ref = E.pkg_ref;
E.pkg_ref++;
E.WriteString(pkg.obj.ident);
E.WriteString(pkg.file_name);
E.WriteString(pkg.key);
}
func (E *Exporter) WriteScope(scope *Globals.Scope) {
if E.debug {
print(" {");
}
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.exported {
E.WriteObject(p.obj);
}
}
E.WriteObject(nil);
if E.debug {
print(" }");
}
}
func (E *Exporter) WriteType(typ *Globals.Type) {
if typ.ref >= 0 {
E.WriteTypeTag(typ.ref); // type already exported
return;
}
if -typ.form >= 0 {
panic("conflict with ref numbers");
}
E.WriteTypeTag(-typ.form);
typ.ref = E.type_ref;
E.type_ref++;
// if we have a named type, export the type identifier and package
ident := "";
if typ.obj != nil {
// named type
if typ.obj.typ != typ {
panic("inconsistent named type");
}
ident = typ.obj.ident;
if !typ.obj.exported {
// the type is invisible (it's identifier is not exported)
// prepend "." to the identifier to make it an illegal
// identifier for importing packages and thus inaccessible
// from those package's source code
ident = "." + ident;
}
}
E.WriteString(ident);
if len(ident) > 0 {
// named type
E.WritePackage(E.comp.pkg_list[typ.obj.pnolev]);
}
switch typ.form {
case Type.VOID:
// for now until we have enough of the front-end working.
case Type.FORWARD:
// corresponding package must be forward-declared too
if typ.obj == nil || E.comp.pkg_list[typ.obj.pnolev].key != "" {
panic("inconsistency in package.type forward declaration");
}
case Type.ALIAS, Type.MAP:
E.WriteType(typ.key);
E.WriteType(typ.elt);
case Type.TUPLE:
E.WriteType(typ.elt);
case Type.ARRAY:
E.WriteInt(typ.len);
E.WriteType(typ.elt);
case Type.CHANNEL:
E.WriteInt(typ.aux);
E.WriteType(typ.elt);
case Type.FUNCTION, Type.METHOD:
E.WriteInt(typ.len);
E.WriteType(typ.elt);
E.WriteScope(typ.scope);
case Type.STRUCT, Type.INTERFACE:
E.WriteScope(typ.scope);
case Type.POINTER:
E.WriteType(typ.elt);
default:
panic("UNREACHABLE");
}
}
func (E *Exporter) WriteObject(obj *Globals.Object) {
if obj == nil {
E.WriteObjectTag(Object.END);
return;
}
E.WriteObjectTag(obj.kind);
if obj.kind == Object.TYPE {
// named types are handled entirely by WriteType()
if obj.typ.obj != obj {
panic("inconsistent named type");
}
E.WriteType(obj.typ);
return;
}
E.WriteString(obj.ident);
E.WriteType(obj.typ);
switch obj.kind {
case Object.CONST:
E.WriteInt(0); // should be the correct value
case Object.VAR, Object.FIELD:
E.WriteInt(0); // should be the correct address/offset
case Object.FUNC:
E.WriteInt(0); // should be the correct address/offset
default:
panic("UNREACHABLE");
}
}
func (E *Exporter) Export(comp* Globals.Compilation) string {
E.comp = comp;
E.debug = comp.flags.debug;
E.buf_pos = 0;
E.pkg_ref = 0;
E.type_ref = 0;
// write magic bits
magic := Platform.MAGIC_obj_file; // TODO remove once len(constant) works
for i := 0; i < len(magic); i++ {
E.WriteByte(magic[i]);
}
// Predeclared types are "pre-exported".
// 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++;
}
}
E.type_ref = Universe.types.len;
// export package 0
pkg := comp.pkg_list[0];
E.WritePackage(pkg);
E.WriteScope(pkg.scope);
if E.debug {
print("\n(", E.buf_pos, " bytes)\n");
}
return string(E.buf)[0 : E.buf_pos];
}
func Export(comp* Globals.Compilation) string {
var E Exporter;
return (&E).Export(comp);
}
// 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 Expr
import Globals "globals"
import Universe "universe"
import Object "object"
import Type "type"
import AST "ast"
// TODO the following shortcuts below don't work due to 6g/6l bugs
//type Compilation Globals.Compilation
//type Expr Globals.Expr
func Error(comp *Globals.Compilation, pos int, msg string) {
comp.env.Error(comp, pos, msg);
}
func Deref(comp *Globals.Compilation, x Globals.Expr) Globals.Expr {
switch typ := x.typ(); typ.form {
case Type.BAD:
// ignore
case Type.POINTER:
x = AST.NewDeref(x);
default:
Error(comp, x.pos(), `"*" not applicable (typ.form = ` + Type.FormStr(typ.form) + `)`);
x = AST.Bad;
}
return x;
}
func Select(comp *Globals.Compilation, x Globals.Expr, pos int, selector string) Globals.Expr {
if x.typ().form == Type.POINTER {
x = Deref(comp, x);
}
switch typ := x.typ(); typ.form {
case Type.BAD:
// ignore
case Type.STRUCT, Type.INTERFACE:
obj := typ.scope.Lookup(selector);
if obj != nil {
x = AST.NewSelector(x.pos(), obj.typ);
} else {
Error(comp, pos, `no field/method "` + selector + `"`);
x = AST.Bad;
}
default:
Error(comp, pos, `"." not applicable (typ.form = ` + Type.FormStr(typ.form) + `)`);
x = AST.Bad;
}
return x;
}
func AssertType(comp *Globals.Compilation, x Globals.Expr, pos int, typ *Globals.Type) Globals.Expr {
return AST.Bad;
}
func Index(comp *Globals.Compilation, x, i Globals.Expr) Globals.Expr {
if x.typ().form == Type.POINTER {
x = Deref(comp, x);
}
switch typ := x.typ(); typ.form {
case Type.BAD:
// ignore
case Type.STRING, Type.ARRAY:
x = AST.Bad;
case Type.MAP:
if Type.Equal(typ.key, i.typ()) {
// x = AST.NewSubscript(x, i1);
x = AST.Bad;
} else {
Error(comp, x.pos(), "map key type mismatch");
x = AST.Bad;
}
default:
Error(comp, x.pos(), `"[]" not applicable (typ.form = ` + Type.FormStr(typ.form) + `)`);
x = AST.Bad;
}
return x;
}
func Slice(comp *Globals.Compilation, x, i, j Globals.Expr) Globals.Expr {
if x.typ().form == Type.POINTER {
x = Deref(comp, x);
}
switch typ := x.typ(); typ.form {
case Type.BAD:
// ignore
break;
case Type.STRING, Type.ARRAY:
x = AST.Bad;
case Type.MAP:
if Type.Equal(typ.key, i.typ()) {
// x = AST.NewSubscript(x, i1);
x = AST.Bad;
} else {
Error(comp, x.pos(), "map key type mismatch");
x = AST.Bad;
}
default:
Error(comp, x.pos(), `"[:]" not applicable (typ.form = ` + Type.FormStr(typ.form) + `)`);
x = AST.Bad;
}
return x;
}
func Call(comp *Globals.Compilation, x Globals.Expr, args *Globals.List) Globals.Expr {
if x.typ().form == Type.POINTER {
x = Deref(comp, x);
}
if x.op() == AST.OBJECT && x.(*AST.Object).obj.kind == Object.BUILTIN {
panic("builtin call - UNIMPLEMENTED");
}
typ := x.typ();
if typ.form == Type.FUNCTION || typ.form == Type.METHOD {
// TODO check args against parameters
}
return AST.Bad;
}
func UnaryExpr(comp *Globals.Compilation, x Globals.Expr) Globals.Expr {
return AST.Bad;
}
func BinaryExpr(comp *Globals.Compilation, x, y Globals.Expr) Globals.Expr {
e := new(AST.BinaryExpr);
e.typ_ = x.typ(); // TODO fix this
//e.op = P.tok; // TODO should we use tokens or separate operator constants?
e.x = x;
e.y = y;
return e;
}
// 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 Compilation 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).
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
}
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
}
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
}
type List struct {
len int;
first, last *Elem;
};
type Scope struct {
parent *Scope;
entries *List;
// entries map[string] *Object; // doesn't work properly
}
type Flags struct {
debug bool;
object_file string;
update_packages bool;
print_interface bool;
verbosity uint;
sixg bool;
token_chan bool;
}
type Environment struct {
Error *(comp *Compilation, pos int, msg string);
Import *(comp *Compilation, pkg_file string) *Package;
Export *(comp *Compilation, pkg_file string);
Compile *(comp *Compilation, src_file string);
}
type Compilation struct {
// environment
flags *Flags;
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;
}
type Expr interface {
op() int; // node operation
pos() int; // source position
typ() *Type;
// ... more to come here
}
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 '+'.
type Elem struct {
next *Elem;
val int;
str string;
obj *Object;
typ *Type;
expr Expr
}
// ----------------------------------------------------------------------------
// Creation
var Universe_void_t *Type // initialized by Universe to Universe.void_t
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_t;
obj.pnolev = 0;
return obj;
}
func NewType(form int) *Type {
typ := new(Type);
typ.ref = -1; // not yet exported
typ.form = form;
return typ;
}
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;
}
func NewList() *List {
return new(List);
}
func NewScope(parent *Scope) *Scope {
scope := new(Scope);
scope.parent = parent;
scope.entries = NewList();
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;
}
// ----------------------------------------------------------------------------
// List methods
func (L *List) at(i int) *Elem {
if i < 0 || L.len <= i {
panic("index out of bounds");
}
p := L.first;
for ; i > 0; i-- {
p = p.next;
}
return p;
}
func (L *List) Clear() {
L.len, L.first, L.last = 0, nil, nil;
}
func (L *List) Add() *Elem {
L.len++;
e := new(Elem);
if L.first == nil {
L.first = e;
} else {
L.last.next = e;
}
L.last = e;
return e;
}
func (L *List) IntAt(i int) int {
return L.at(i).val;
}
func (L *List) StrAt(i int) string {
return L.at(i).str;
}
func (L *List) ObjAt(i int) *Object {
return L.at(i).obj;
}
func (L *List) TypAt(i int) *Type {
return L.at(i).typ;
}
func (L *List) ExprAt(i int) Expr {
return L.at(i).expr;
}
func (L *List) AddInt(val int) {
L.Add().val = val;
}
func (L *List) AddStr(str string) {
L.Add().str = str;
}
func (L *List) AddObj(obj *Object) {
L.Add().obj = obj;
}
func (L *List) AddTyp(typ *Type) {
L.Add().typ = typ;
}
func (L *List) AddExpr(expr Expr) {
L.Add().expr = expr;
}
// ----------------------------------------------------------------------------
// Scope methods
func (scope *Scope) Lookup(ident string) *Object {
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.ident == ident {
return p.obj;
}
}
return nil;
}
func (scope *Scope) Add(obj* Object) {
scope.entries.AddObj(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 p := scope.entries.first; p != nil; p = p.next {
print("\n ", p.obj.ident);
}
print("\n}\n");
}
// ----------------------------------------------------------------------------
// Compilation methods
func (C *Compilation) 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 *Compilation) 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 main
import Build "build"
import Globals "globals"
import Compilation "compilation"
func PrintHelp() {
print(
"go (" + Build.time + ")\n" +
"usage:\n" +
" go { flag } { file }\n" +
" -d debug mode, additional self tests and prints\n" +
" -o file explicit object file\n" +
" -r recursively update imported packages in current directory\n" +
" -p print package interface\n" +
" -v [0 .. 3] verbosity level\n" +
" -6g 6g compatibility mode\n" +
" -token_chan use token channel to scan and parse in parallel\n"
);
}
var argno int = 1;
func Next() string {
arg := "";
if argno < len(sys.Args) {
arg = sys.Args[argno];
argno++;
}
return arg;
}
func main() {
arg := Next();
if arg == "" {
PrintHelp();
return;
}
// collect flags and files
flags := new(Globals.Flags);
files := Globals.NewList();
for arg != "" {
switch arg {
case "-d": flags.debug = true;
case "-o": flags.object_file = Next();
print("note: -o flag ignored at the moment\n");
case "-r": flags.update_packages = true;
case "-p": flags.print_interface = true;
case "-v":
arg = Next();
switch arg {
case "0", "1", "2", "3":
flags.verbosity = uint(arg[0] - '0');
default:
// anything else is considered the next argument
flags.verbosity = 1;
continue;
}
case "-6g": flags.sixg = true;
case "-token_chan": flags.token_chan = true;
default: files.AddStr(arg);
}
arg = Next();
}
// setup environment
env := new(Globals.Environment);
env.Error = &Compilation.Error;
env.Import = &Compilation.Import;
env.Export = &Compilation.Export;
env.Compile = &Compilation.Compile;
// compile files
for p := files.first; p != nil; p = p.next {
// setup compilation
comp := new(Globals.Compilation);
comp.flags = flags;
comp.env = env;
// compile
Compilation.Compile(comp, p.str);
}
}
// 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 Platform "platform"
import Utils "utils"
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
type Importer struct {
comp *Globals.Compilation;
debug bool;
buf string;
buf_pos int;
pkg_list [256] *Globals.Package;
pkg_ref int;
type_list [1024] *Globals.Type;
type_ref int;
};
func (I *Importer) ReadObject() *Globals.Object;
func (I *Importer) ReadByte() byte {
x := I.buf[I.buf_pos];
I.buf_pos++;
/*
if E.debug {
print(" ", x);
}
*/
return x;
}
func (I *Importer) ReadInt() int {
x := 0;
s := uint(0);
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) ReadPackageTag() int {
tag := I.ReadInt();
if I.debug {
if tag >= 0 {
print(" [P", tag, "]"); // package ref
} else {
print("\nP", I.pkg_ref, ":");
}
}
return tag;
}
func (I *Importer) ReadTypeTag() int {
tag := I.ReadInt();
if I.debug {
if tag >= 0 {
print(" [T", tag, "]"); // type ref
} else {
print("\nT", I.type_ref, ": ", Type.FormStr(-tag));
}
}
return tag;
}
func (I *Importer) ReadObjectTag() int {
tag := I.ReadInt();
if tag < 0 {
panic("tag < 0");
}
if I.debug {
print("\n", Object.KindStr(tag));
}
return tag;
}
func (I *Importer) ReadPackage() *Globals.Package {
tag := I.ReadPackageTag();
if tag >= 0 {
return I.pkg_list[tag]; // package already imported
}
ident := I.ReadString();
file_name := I.ReadString();
key := I.ReadString();
// Canonicalize package - if it was imported before,
// use the primary import.
pkg := I.comp.Lookup(file_name);
if pkg == nil {
// new package
obj := Globals.NewObject(-1, Object.PACKAGE, ident);
pkg = Globals.NewPackage(file_name, obj, Globals.NewScope(nil));
I.comp.Insert(pkg);
if I.comp.flags.verbosity > 1 {
print(`import: implicitly adding package `, ident, ` "`, file_name, `" (pno = `, obj.pnolev, ")\n");
}
} else if key != "" && key != pkg.key {
// the package was imported before but the package
// key has changed (a "" key indicates a forward-
// declared package - it's key is consistent with
// any actual package of the same name)
panic("package key inconsistency");
}
I.pkg_list[I.pkg_ref] = pkg;
I.pkg_ref++;
return pkg;
}
func (I *Importer) ReadScope(scope *Globals.Scope, allow_multiples bool) {
if I.debug {
print(" {");
}
obj := I.ReadObject();
for obj != nil {
// allow_multiples is for debugging only - we should never
// have multiple imports where we don't expect them
if allow_multiples {
scope.InsertImport(obj);
} else {
scope.Insert(obj);
}
obj = I.ReadObject();
}
if I.debug {
print(" }");
}
}
func (I *Importer) ReadType() *Globals.Type {
tag := I.ReadTypeTag();
if tag >= 0 {
return I.type_list[tag]; // type already imported
}
typ := Globals.NewType(-tag);
ptyp := typ; // primary type
ident := I.ReadString();
if len(ident) > 0 {
// named type
pkg := I.ReadPackage();
// create corresponding type object
obj := Globals.NewObject(0, Object.TYPE, ident);
obj.exported = true;
obj.typ = typ;
obj.pnolev = pkg.obj.pnolev;
typ.obj = obj;
// canonicalize type
// (if the type was seen before, use primary instance!)
ptyp = pkg.scope.InsertImport(obj).typ;
}
// insert the primary type into the type table but
// keep filling in the current type fields
I.type_list[I.type_ref] = ptyp;
I.type_ref++;
switch (typ.form) {
case Type.VOID:
// for now until we have enough of the front-end working
// change the form to BAD to avoid error messages
typ.form = Type.BAD;
case Type.FORWARD:
typ.scope = Globals.NewScope(nil);
case Type.TUPLE:
typ.elt = I.ReadType();
case Type.ALIAS, Type.MAP:
typ.key = I.ReadType();
typ.elt = I.ReadType();
case Type.ARRAY:
typ.len = I.ReadInt();
typ.elt = I.ReadType();
case Type.CHANNEL:
typ.aux = I.ReadInt();
typ.elt = I.ReadType();
case Type.FUNCTION, Type.METHOD:
typ.len = I.ReadInt();
typ.elt = I.ReadType();
typ.scope = Globals.NewScope(nil);
I.ReadScope(typ.scope, false);
case Type.STRUCT, Type.INTERFACE:
typ.scope = Globals.NewScope(nil);
I.ReadScope(typ.scope, false);
case Type.POINTER:
typ.elt = I.ReadType();
default:
panic("UNREACHABLE");
}
return ptyp; // only use primary type
}
func (I *Importer) ReadObject() *Globals.Object {
tag := I.ReadObjectTag();
if tag == Object.END {
return nil;
}
if tag == Object.TYPE {
// named types are handled entirely by ReadType()
typ := I.ReadType();
if typ.obj.typ != typ {
panic("inconsistent named type");
}
return typ.obj;
}
ident := I.ReadString();
obj := Globals.NewObject(0, tag, ident);
obj.exported = true;
obj.typ = I.ReadType();
switch (tag) {
case Object.CONST:
I.ReadInt(); // should set the value field
case Object.VAR, Object.FIELD:
I.ReadInt(); // should set the address/offset field
case Object.FUNC:
I.ReadInt(); // should set the address/offset field
default:
panic("UNREACHABLE");
}
return obj;
}
func (I *Importer) Import(comp* Globals.Compilation, data string) *Globals.Package {
I.comp = comp;
I.debug = comp.flags.debug;
I.buf = data;
I.buf_pos = 0;
I.pkg_ref = 0;
I.type_ref = 0;
// check magic bits
if !Utils.Contains(data, Platform.MAGIC_obj_file, 0) {
return nil;
}
// Predeclared types are "pre-imported".
for p := Universe.types.first; p != nil; p = p.next {
if p.typ.ref != I.type_ref {
panic("incorrect ref for predeclared type");
}
I.type_list[I.type_ref] = p.typ;
I.type_ref++;
}
// import package
pkg := I.ReadPackage();
I.ReadScope(pkg.scope, true);
if I.debug {
print("\n(", I.buf_pos, " bytes)\n");
}
return pkg;
}
func Import(comp *Globals.Compilation, data string) *Globals.Package {
var I Importer;
pkg := (&I).Import(comp, data);
return pkg;
}
// 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"
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.
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>";
}
This diff is collapsed.
// 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 Platform
import Utils "utils"
// ----------------------------------------------------------------------------
// Environment
var
GOARCH,
GOOS,
GOROOT,
USER string;
func GetEnv(key string) string {
n := len(key);
for i := 0; i < sys.envc(); i++ {
v := sys.envv(i);
if n < len(v) && v[0 : n] == key && v[n] == '=' {
return v[n + 1 : len(v)]; // +1: trim "="
}
}
return "";
}
func init() {
GOARCH = GetEnv("GOARCH");
GOOS = GetEnv("GOOS");
GOROOT = GetEnv("GOROOT");
USER = GetEnv("USER");
}
// ----------------------------------------------------------------------------
// I/O
const (
MAGIC_obj_file = "@gri-go.7@v0"; // make it clear thar it cannot be a source file
src_file_ext = ".go";
obj_file_ext = ".7";
)
func ReadObjectFile(filename string) (data string, ok bool) {
data, ok = sys.readfile(filename + obj_file_ext);
magic := MAGIC_obj_file; // TODO remove once len(constant) works
if ok && len(data) >= len(magic) && data[0 : len(magic)] == magic {
return data, ok;
}
return "", false;
}
func ReadSourceFile(name string) (data string, ok bool) {
name = Utils.TrimExt(name, src_file_ext) + src_file_ext;
data, ok = sys.readfile(name);
return data, ok;
}
func WriteObjectFile(name string, data string) bool {
name = Utils.TrimExt(Utils.BaseName(name), src_file_ext) + obj_file_ext;
return sys.writefile(name, data);
}
// 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 Printer
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
type Printer struct {
comp *Globals.Compilation;
print_all bool;
level int;
};
func (P *Printer) PrintObjectStruct(obj *Globals.Object);
func (P *Printer) PrintObject(obj *Globals.Object);
func (P *Printer) PrintTypeStruct(typ *Globals.Type);
func (P *Printer) PrintType(typ *Globals.Type);
func (P *Printer) Init(comp *Globals.Compilation, print_all bool) {
P.comp = comp;
P.print_all = print_all;
P.level = 0;
}
func IsAnonymous(name string) bool {
return len(name) == 0 || name[0] == '.';
}
func (P *Printer) PrintSigRange(typ *Globals.Type, a, b int) {
scope := typ.scope;
if a + 1 == b && IsAnonymous(scope.entries.ObjAt(a).ident) {
P.PrintType(scope.entries.ObjAt(a).typ); // result type only
} else {
print("(");
for i := a; i < b; i++ {
par := scope.entries.ObjAt(i);
if i > a {
print(", ");
}
print(par.ident, " ");
P.PrintType(par.typ);
}
print(")");
}
}
func (P *Printer) PrintSignature(typ *Globals.Type, fun *Globals.Object) {
p0 := 0;
if typ.form == Type.METHOD {
p0 = 1;
} else {
if typ.form != Type.FUNCTION {
panic("not a function or method");
}
}
r0 := p0 + typ.len;
l0 := typ.scope.entries.len;
if P.level == 0 {
print("func ");
if 0 < p0 {
P.PrintSigRange(typ, 0, p0);
print(" ");
}
}
if fun != nil {
P.PrintObject(fun);
//print(" ");
} else if p0 > 0 {
print(". ");
}
P.PrintSigRange(typ, p0, r0);
if r0 < l0 {
print(" ");
P.PrintSigRange(typ, r0, l0);
}
}
func (P *Printer) PrintIndent() {
print("\n");
for i := P.level; i > 0; i-- {
print("\t");
}
}
func (P *Printer) PrintScope(scope *Globals.Scope, delta int) {
// determine the number of scope entries to print
var n int;
if P.print_all {
n = scope.entries.len;
} else {
n = 0;
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.exported && !IsAnonymous(p.obj.ident) {
n++;
}
}
}
// print the scope
const scale = 2;
if n > 0 {
P.level += delta;
for p := scope.entries.first; p != nil; p = p.next {
if P.print_all || p.obj.exported && !IsAnonymous(p.obj.ident) {
P.PrintIndent();
P.PrintObjectStruct(p.obj);
}
}
P.level -= delta;
P.PrintIndent();
}
}
func (P *Printer) PrintObjectStruct(obj *Globals.Object) {
switch obj.kind {
case Object.BAD:
P.PrintObject(obj);
print(" /* bad */");
case Object.CONST:
print("const ");
P.PrintObject(obj);
print(" ");
P.PrintType(obj.typ);
case Object.TYPE:
print("type ");
P.PrintObject(obj);
print(" ");
P.PrintTypeStruct(obj.typ);
case Object.VAR:
print("var ");
fallthrough;
case Object.FIELD:
P.PrintObject(obj);
print(" ");
P.PrintType(obj.typ);
case Object.FUNC:
P.PrintSignature(obj.typ, obj);
case Object.BUILTIN:
P.PrintObject(obj);
print(" /* builtin */");
case Object.PACKAGE:
print("package ");
P.PrintObject(obj);
print(" ");
P.PrintScope(P.comp.pkg_list[obj.pnolev].scope, 0);
default:
panic("UNREACHABLE");
}
if P.level > 0 {
print(";");
}
}
func (P *Printer) PrintObject(obj *Globals.Object) {
if obj.pnolev > 0 {
pkg := P.comp.pkg_list[obj.pnolev];
if pkg.key == "" {
// forward-declared package
print(`"`, pkg.file_name, `"`);
} else {
// imported package
print(pkg.obj.ident);
}
print(".");
}
print(obj.ident);
}
func (P *Printer) PrintTypeStruct(typ *Globals.Type) {
switch typ.form {
case Type.VOID:
print("void");
case Type.BAD:
print("<bad type>");
case Type.FORWARD:
print("<forward type>");
case Type.TUPLE:
print("<tuple type>");
case Type.NIL, Type.BOOL, Type.UINT, Type.INT, Type.FLOAT, Type.STRING, Type.ANY:
if typ.obj == nil {
panic("typ.obj == nil");
}
P.PrintType(typ);
case Type.ALIAS:
P.PrintType(typ.elt);
if typ.key != typ.elt {
print(" /* ");
P.PrintType(typ.key);
print(" */");
}
case Type.ARRAY:
print("[]");
P.PrintType(typ.elt);
case Type.STRUCT:
print("struct {");
P.PrintScope(typ.scope, 1);
print("}");
case Type.INTERFACE:
print("interface {");
P.PrintScope(typ.scope, 1);
print("}");
case Type.MAP:
print("map [");
P.PrintType(typ.key);
print("] ");
P.PrintType(typ.elt);
case Type.CHANNEL:
switch typ.aux {
case Type.SEND: print("chan <- ");
case Type.RECV: print("<- chan ");
case Type.SEND + Type.RECV: print("chan ");
default: panic("UNREACHABLE");
}
P.PrintType(typ.elt);
case Type.FUNCTION:
P.PrintSignature(typ, nil);
case Type.POINTER:
print("*");
P.PrintType(typ.elt);
default:
panic("UNREACHABLE");
}
}
func (P *Printer) PrintType(typ *Globals.Type) {
if typ.obj != nil {
P.PrintObject(typ.obj);
} else {
P.PrintTypeStruct(typ);
}
}
func PrintObject(comp *Globals.Compilation, obj *Globals.Object, print_all bool) {
var P Printer;
(&P).Init(comp, print_all);
(&P).PrintObjectStruct(obj);
print("\n");
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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