Commit 4b0b7d8d authored by Robert Griesemer's avatar Robert Griesemer

- import and export code, bug fixes

- almost back to where I was in C++, but now all in Go

R=r
OCL=13627
CL=13627
parent ebec9917
// 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 Node struct {
left, right *Node;
val bool
}
export Node
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package Compilation package Compilation
import Utils "utils"
import Globals "globals" import Globals "globals"
import Object "object" import Object "object"
import Type "type" import Type "type"
...@@ -14,28 +15,6 @@ import Parser "parser" ...@@ -14,28 +15,6 @@ import Parser "parser"
import Export "export" import Export "export"
func BaseName(s string) string {
// TODO this is not correct for non-ASCII strings!
i := len(s) - 1;
for i >= 0 && s[i] != '/' {
if s[i] > 128 {
panic "non-ASCII string"
}
i--;
}
return s[i + 1 : len(s)];
}
func FixExt(s string) string {
i := len(s) - 3; // 3 == len(".go");
if s[i : len(s)] == ".go" {
s = s[0 : i];
}
return s + ".7";
}
export Compile export Compile
func Compile(file_name string, verbose int) { func Compile(file_name string, verbose int) {
src, ok := sys.readfile(file_name); src, ok := sys.readfile(file_name);
...@@ -47,11 +26,6 @@ func Compile(file_name string, verbose int) { ...@@ -47,11 +26,6 @@ func Compile(file_name string, verbose int) {
Universe.Init(); // TODO eventually this should be only needed once Universe.Init(); // TODO eventually this should be only needed once
comp := Globals.NewCompilation(); comp := Globals.NewCompilation();
pkg := Globals.NewPackage(file_name);
comp.Insert(pkg);
if comp.npkgs != 1 {
panic "should have exactly one package now";
}
scanner := new(Scanner.Scanner); scanner := new(Scanner.Scanner);
scanner.Open(file_name, src); scanner.Open(file_name, src);
...@@ -66,8 +40,6 @@ func Compile(file_name string, verbose int) { ...@@ -66,8 +40,6 @@ func Compile(file_name string, verbose int) {
} }
// export // export
/*
exp := new(Export.Exporter); exp := new(Export.Exporter);
exp.Export(comp, FixExt(BaseName(file_name))); exp.Export(comp, Utils.FixExt(Utils.BaseName(file_name)));
*/
} }
// 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" // this fails
import base "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
type Node1 *base2.Node
type T0 byte
type T1 T0
type (
T2 [10]T0;
T3 map [string] int;
T4 struct {
f1, f2, f3 int;
f4 [] float;
};
T5 *T4;
)
type F0 func ()
type F1 func (a int)
type F2 func (a, b int, c float)
type F3 func () bool
type F4 func (a int) (z T5, ok bool)
type F5 func (a, b int, c float) (z T5, ok bool)
type F6 func (a int, b float) bool
type F7 func (a int, b float, c, d *bool) bool
type (
M0 func (p T5) . ();
M1 func (p T5) . (a int);
M2 func (p T5) . (a, b int, c float);
M3 func (p T5) . () bool;
M4 func (p T5) . (a int) (z T5, ok bool);
M5 func (p T5) . (a, b int, c float) (z T5, ok bool);
)
type T6 chan int
type T7 chan<- T6
type T8 chan-< T6
type T9 struct {
p *T9;
q [] map [int] *T9;
f *func(x, y *T9) *T9;
}
type T10;
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 {}
func f4(a int) (z T5, ok bool) {}
func f5(a, b int, c float) (z T5, ok bool) {}
func (p *T4) m0() {}
func (p *T4) m1(a int) {}
func (p *T4) m2(a, b int, c float) {}
func (p *T4) m3() bool {}
func (p *T4) m4(a int) (z T5, ok bool) {}
func (p *T4) m5(a, b int, c float) (z T5, ok bool) {
L: var x = a;
}
export c0, c1, v2, v3
export T0, T1, T4, T4, T4, M0, M5, I2, f0, f1, Node0, Node1
...@@ -38,29 +38,30 @@ func (E *Exporter) WriteByte(x byte) { ...@@ -38,29 +38,30 @@ func (E *Exporter) WriteByte(x byte) {
func (E *Exporter) WriteInt(x int) { func (E *Exporter) WriteInt(x int) {
/* x0 := x;
if E.debug {
print " #", x;
}
*/
for x < -64 || x >= 64 { for x < -64 || x >= 64 {
E.WriteByte(byte(x & 127)); E.WriteByte(byte(x & 127));
x = int(uint(x >> 7)); // arithmetic shift x = int(uint(x >> 7)); // arithmetic shift
} }
// -64 <= x && x < 64 // -64 <= x && x < 64
E.WriteByte(byte(x + 192)); E.WriteByte(byte(x + 192));
/*
if E.debug {
print " #", x0;
}
*/
} }
func (E *Exporter) WriteString(s string) { func (E *Exporter) WriteString(s string) {
if E.debug {
print ` "`, s, `"`;
}
n := len(s); n := len(s);
E.WriteInt(n); E.WriteInt(n);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
E.WriteByte(s[i]); E.WriteByte(s[i]);
} }
if E.debug {
print ` "`, s, `"`;
}
} }
...@@ -68,14 +69,15 @@ func (E *Exporter) WriteObjTag(tag int) { ...@@ -68,14 +69,15 @@ func (E *Exporter) WriteObjTag(tag int) {
if tag < 0 { if tag < 0 {
panic "tag < 0"; panic "tag < 0";
} }
E.WriteInt(tag);
if E.debug { if E.debug {
print "\nObj: ", tag; // obj kind print "\nObj: ", tag; // obj kind
} }
E.WriteInt(tag);
} }
func (E *Exporter) WriteTypeTag(tag int) { func (E *Exporter) WriteTypeTag(tag int) {
E.WriteInt(tag);
if E.debug { if E.debug {
if tag > 0 { if tag > 0 {
print "\nTyp ", E.type_ref, ": ", tag; // type form print "\nTyp ", E.type_ref, ": ", tag; // type form
...@@ -83,11 +85,11 @@ func (E *Exporter) WriteTypeTag(tag int) { ...@@ -83,11 +85,11 @@ func (E *Exporter) WriteTypeTag(tag int) {
print " [Typ ", -tag, "]"; // type ref print " [Typ ", -tag, "]"; // type ref
} }
} }
E.WriteInt(tag);
} }
func (E *Exporter) WritePackageTag(tag int) { func (E *Exporter) WritePackageTag(tag int) {
E.WriteInt(tag);
if E.debug { if E.debug {
if tag > 0 { if tag > 0 {
print "\nPkg ", E.pkg_ref, ": ", tag; // package no print "\nPkg ", E.pkg_ref, ": ", tag; // package no
...@@ -95,7 +97,6 @@ func (E *Exporter) WritePackageTag(tag int) { ...@@ -95,7 +97,6 @@ func (E *Exporter) WritePackageTag(tag int) {
print " [Pkg ", -tag, "]"; // package ref print " [Pkg ", -tag, "]"; // package ref
} }
} }
E.WriteInt(tag);
} }
...@@ -119,6 +120,7 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) { ...@@ -119,6 +120,7 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) {
n++; n++;
} }
} }
E.WriteInt(n);
// export the objects, if any // export the objects, if any
if n > 0 { if n > 0 {
...@@ -149,7 +151,7 @@ func (E *Exporter) WriteObject(obj *Globals.Object) { ...@@ -149,7 +151,7 @@ func (E *Exporter) WriteObject(obj *Globals.Object) {
E.WriteObjTag(obj.kind); E.WriteObjTag(obj.kind);
E.WriteString(obj.ident); E.WriteString(obj.ident);
E.WriteType(obj.typ); E.WriteType(obj.typ);
//E.WritePackage(E.comp.pkgs[obj.pnolev]); E.WritePackage(E.comp.pkgs[obj.pnolev]);
switch obj.kind { switch obj.kind {
case Object.CONST: case Object.CONST:
...@@ -249,16 +251,16 @@ func (E *Exporter) WritePackage(pkg *Globals.Package) { ...@@ -249,16 +251,16 @@ func (E *Exporter) WritePackage(pkg *Globals.Package) {
func (E *Exporter) Export(comp* Globals.Compilation, file_name string) { func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
if E.debug {
print "exporting to ", file_name;
}
E.comp = comp; E.comp = comp;
E.debug = true; E.debug = false;
E.pos = 0; E.pos = 0;
E.pkg_ref = 0; E.pkg_ref = 0;
E.type_ref = 0; E.type_ref = 0;
if E.debug {
print "exporting to ", file_name, "\n";
}
// Predeclared types are "pre-exported". // Predeclared types are "pre-exported".
// TODO run the loop below only in debug mode // TODO run the loop below only in debug mode
{ i := 0; { i := 0;
......
...@@ -280,6 +280,7 @@ func (C *Compilation) Insert(pkg *Package) { ...@@ -280,6 +280,7 @@ func (C *Compilation) Insert(pkg *Package) {
if C.Lookup(pkg.file_name) != nil { if C.Lookup(pkg.file_name) != nil {
panic "package already inserted"; panic "package already inserted";
} }
pkg.obj.pnolev = C.npkgs;
C.pkgs[C.npkgs] = pkg; C.pkgs[C.npkgs] = pkg;
C.npkgs++; C.npkgs++;
} }
......
...@@ -10,6 +10,7 @@ import Type "type" ...@@ -10,6 +10,7 @@ import Type "type"
import Universe "universe" import Universe "universe"
export Importer // really only want to export Import()
type Importer struct { type Importer struct {
comp *Globals.Compilation; comp *Globals.Compilation;
debug bool; debug bool;
...@@ -257,6 +258,7 @@ func (I *Importer) ReadPackage() *Globals.Package { ...@@ -257,6 +258,7 @@ func (I *Importer) ReadPackage() *Globals.Package {
if pkg == nil { if pkg == nil {
// new package // new package
pkg = Globals.NewPackage(file_name); pkg = Globals.NewPackage(file_name);
pkg.obj = Globals.NewObject(-1, Object.PACKAGE, ident);
pkg.scope = Globals.NewScope(nil); pkg.scope = Globals.NewScope(nil);
pkg = I.comp.InsertImport(pkg); pkg = I.comp.InsertImport(pkg);
...@@ -271,24 +273,25 @@ func (I *Importer) ReadPackage() *Globals.Package { ...@@ -271,24 +273,25 @@ func (I *Importer) ReadPackage() *Globals.Package {
} }
func (I *Importer) Import(comp* Globals.Compilation, file_name string) { 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;
if I.debug { if I.debug {
print "importing from ", file_name; print "importing from ", file_name, "\n";
} }
buf, ok := sys.readfile(file_name); buf, ok := sys.readfile(file_name);
if !ok { if !ok {
panic "import failed"; return nil;
} }
I.comp = comp;
I.debug = true;
I.buf = buf; I.buf = buf;
I.pos = 0;
I.npkgs = 0;
I.ntypes = 0;
// Predeclared types are "pre-exported". // Predeclared types are "pre-imported".
for p := Universe.types.first; p != nil; p = p.next { for p := Universe.types.first; p != nil; p = p.next {
if p.typ.ref != I.ntypes { if p.typ.ref != I.ntypes {
panic "incorrect ref for predeclared type"; panic "incorrect ref for predeclared type";
...@@ -311,4 +314,6 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) { ...@@ -311,4 +314,6 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) {
if I.debug { if I.debug {
print "\n(", I.pos, " bytes)\n"; print "\n(", I.pos, " bytes)\n";
} }
return pkg;
} }
...@@ -4,11 +4,13 @@ ...@@ -4,11 +4,13 @@
package Parser package Parser
import Utils "utils"
import Scanner "scanner" import Scanner "scanner"
import Globals "globals" import Globals "globals"
import Object "object" import Object "object"
import Type "type" import Type "type"
import Universe "universe" import Universe "universe"
import Import "import"
import AST "ast" import AST "ast"
...@@ -28,6 +30,7 @@ type Parser struct { ...@@ -28,6 +30,7 @@ type Parser struct {
val string; // token value (for IDENT, NUMBER, STRING only) val string; // token value (for IDENT, NUMBER, STRING only)
// Semantic analysis // Semantic analysis
level int; // 0 = global scope, -1 = function scope of global functions, etc.
top_scope *Globals.Scope; top_scope *Globals.Scope;
undef_types *Globals.List; undef_types *Globals.List;
exports *Globals.List; exports *Globals.List;
...@@ -77,6 +80,7 @@ func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int ...@@ -77,6 +80,7 @@ func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int
P.indent = 0; P.indent = 0;
P.S = S; P.S = S;
P.Next(); P.Next();
P.level = 0;
P.top_scope = Universe.scope; P.top_scope = Universe.scope;
P.undef_types = Globals.NewList(); P.undef_types = Globals.NewList();
P.exports = Globals.NewList(); P.exports = Globals.NewList();
...@@ -128,7 +132,11 @@ func (P *Parser) Lookup(ident string) *Globals.Object { ...@@ -128,7 +132,11 @@ func (P *Parser) Lookup(ident string) *Globals.Object {
func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) { func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
if EnableSemanticTests && scope.Lookup(obj.ident) != nil { if !EnableSemanticTests {
return;
}
obj.pnolev = P.level;
if scope.Lookup(obj.ident) != nil {
P.Error(obj.pos, `"` + obj.ident + `" is declared already`); P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
return; // don't insert it into the scope return; // don't insert it into the scope
} }
...@@ -141,6 +149,77 @@ func (P *Parser) Declare(obj *Globals.Object) { ...@@ -141,6 +149,77 @@ func (P *Parser) Declare(obj *Globals.Object) {
} }
func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
// Determine if we have a receiver or not.
if p0 > 0 && check_recv {
// method
if p0 != 1 {
panic "p0 != 1";
}
}
typ := Globals.NewType(Type.FUNCTION);
if p0 == 0 {
typ.flags = 0;
} else {
typ.flags = Type.RECV;
}
typ.len_ = r0 - p0;
typ.scope = sig;
return typ;
}
func (P *Parser) DeclareFunc(exported bool, ident string, typ *Globals.Type) *Globals.Object {
// Determine scope.
scope := P.top_scope;
if typ.flags & Type.RECV != 0 {
// method - declare in corresponding struct
if typ.scope.entries.len_ < 1 {
panic "no recv in signature?";
}
trecv := typ.scope.entries.first.typ;
if trecv.form == Type.POINTER {
trecv = trecv.elt;
}
scope = trecv.scope;
}
// Declare the function.
fun := scope.Lookup(ident);
if fun == nil {
fun = Globals.NewObject(-1, Object.FUNC, ident);
fun.typ = typ;
// TODO do we need to set the prymary type? probably...
P.DeclareInScope(scope, fun);
return fun;
}
// fun != NULL: possibly a forward declaration.
if (fun.kind != Object.FUNC) {
P.Error(-1, `"` + ident + `" is declared already`);
// Continue but do not insert this function into the scope.
fun = Globals.NewObject(-1, Object.FUNC, ident);
fun.typ = typ;
// TODO do we need to set the prymary type? probably...
return fun;
}
// We have a function with the same name.
/*
if (!EqualTypes(type, fun->type())) {
this->Error("type of \"%s\" does not match its forward declaration", name.cstr());
// Continue but do not insert this function into the scope.
NewObject(Object::FUNC, name);
fun->set_type(type);
return fun;
}
*/
// We have a matching forward declaration. Use it.
return fun;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Common productions // Common productions
...@@ -225,10 +304,23 @@ func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object { ...@@ -225,10 +304,23 @@ func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
} }
if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD { if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
panic "Qualified ident not complete yet"; if obj.pnolev < 0 {
P.Next(); panic "obj.pnolev < 0";
P.ParseIdent(); }
pkg := P.comp.pkgs[obj.pnolev];
//if pkg.obj.ident != ident {
// panic "pkg.obj.ident != ident";
//}
P.Next(); // consume "."
pos = P.pos;
ident = P.ParseIdent();
obj = pkg.scope.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared in package "` + pkg.obj.ident + `"`);
obj = Globals.NewObject(pos, Object.BAD, ident);
} }
}
P.Ecart(); P.Ecart();
return obj; return obj;
...@@ -383,26 +475,6 @@ func (P *Parser) TryResult() bool { ...@@ -383,26 +475,6 @@ func (P *Parser) TryResult() bool {
} }
func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
// Determine if we have a receiver or not.
if p0 > 0 && check_recv {
// method
if p0 != 1 {
panic "p0 != 1";
}
}
typ := Globals.NewType(Type.FUNCTION);
if p0 == 0 {
typ.flags = 0;
} else {
typ.flags = Type.RECV;
}
typ.len_ = r0 - p0;
typ.scope = sig;
return typ;
}
// Anonymous signatures // Anonymous signatures
// //
// (params) // (params)
...@@ -424,9 +496,9 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type { ...@@ -424,9 +496,9 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type {
if P.tok == Scanner.PERIOD { if P.tok == Scanner.PERIOD {
p0 = sig.entries.len_; p0 = sig.entries.len_;
if (p0 != 1) { if (EnableSemanticTests && p0 != 1) {
P.Error(recv_pos, "must have exactly one receiver") P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED"; panic "UNIMPLEMENTED (ParseAnonymousSignature)";
// TODO do something useful here // TODO do something useful here
} }
P.Next(); P.Next();
...@@ -462,10 +534,10 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) { ...@@ -462,10 +534,10 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
recv_pos := P.pos; recv_pos := P.pos;
P.ParseParameters(); P.ParseParameters();
p0 = sig.entries.len_; p0 = sig.entries.len_;
if (p0 != 1) { if (EnableSemanticTests && p0 != 1) {
print "p0 = ", p0, "\n"; print "p0 = ", p0, "\n";
P.Error(recv_pos, "must have exactly one receiver") P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED"; panic "UNIMPLEMENTED (ParseNamedSignature)";
// TODO do something useful here // TODO do something useful here
} }
} }
...@@ -498,8 +570,13 @@ func (P *Parser) ParseMethodDecl() { ...@@ -498,8 +570,13 @@ func (P *Parser) ParseMethodDecl() {
P.Trace("MethodDecl"); P.Trace("MethodDecl");
P.ParseIdent(); P.ParseIdent();
P.OpenScope();
sig := P.top_scope;
p0 := 0;
P.ParseParameters(); P.ParseParameters();
r0 := sig.entries.len_;
P.TryResult(); P.TryResult();
P.CloseScope();
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
P.Ecart(); P.Ecart();
...@@ -662,15 +739,26 @@ func (P *Parser) ParseStatementList() { ...@@ -662,15 +739,26 @@ func (P *Parser) ParseStatementList() {
} }
func (P *Parser) ParseBlock() { func (P *Parser) ParseBlock(sig *Globals.Scope) {
P.Trace("Block"); P.Trace("Block");
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
P.OpenScope(); P.OpenScope();
if sig != nil {
P.level--;
// add function parameters to scope
scope := P.top_scope;
for p := sig.entries.first; p != nil; p = p.next {
scope.Insert(p.obj)
}
}
if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
P.ParseStatementList(); P.ParseStatementList();
} }
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
if sig != nil {
P.level++;
}
P.CloseScope(); P.CloseScope();
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
...@@ -717,8 +805,8 @@ func (P *Parser) ParseNew() { ...@@ -717,8 +805,8 @@ func (P *Parser) ParseNew() {
func (P *Parser) ParseFunctionLit() { func (P *Parser) ParseFunctionLit() {
P.Trace("FunctionLit"); P.Trace("FunctionLit");
P.ParseFunctionType(); typ := P.ParseFunctionType();
P.ParseBlock(); P.ParseBlock(typ.scope);
P.Ecart(); P.Ecart();
} }
...@@ -1226,7 +1314,7 @@ func (P *Parser) ParseIfStat() *AST.IfStat { ...@@ -1226,7 +1314,7 @@ func (P *Parser) ParseIfStat() *AST.IfStat {
} }
} }
} }
P.ParseBlock(); P.ParseBlock(nil);
if P.tok == Scanner.ELSE { if P.tok == Scanner.ELSE {
P.Next(); P.Next();
if P.tok == Scanner.IF { if P.tok == Scanner.IF {
...@@ -1262,7 +1350,7 @@ func (P *Parser) ParseForStat() { ...@@ -1262,7 +1350,7 @@ func (P *Parser) ParseForStat() {
} }
} }
} }
P.ParseBlock(); P.ParseBlock(nil);
P.CloseScope(); P.CloseScope();
P.Ecart(); P.Ecart();
...@@ -1389,7 +1477,7 @@ func (P *Parser) ParseRangeStat() bool { ...@@ -1389,7 +1477,7 @@ func (P *Parser) ParseRangeStat() bool {
P.ParseIdentList(); P.ParseIdentList();
P.Expect(Scanner.DEFINE); P.Expect(Scanner.DEFINE);
P.ParseExpression(); P.ParseExpression();
P.ParseBlock(); P.ParseBlock(nil);
P.Ecart(); P.Ecart();
} }
...@@ -1431,7 +1519,7 @@ func (P *Parser) TryStatement() bool { ...@@ -1431,7 +1519,7 @@ func (P *Parser) TryStatement() bool {
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.ParseControlFlowStat(P.tok); P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE: case Scanner.LBRACE:
P.ParseBlock(); P.ParseBlock(nil);
case Scanner.IF: case Scanner.IF:
P.ParseIfStat(); P.ParseIfStat();
case Scanner.FOR: case Scanner.FOR:
...@@ -1461,30 +1549,32 @@ func (P *Parser) TryStatement() bool { ...@@ -1461,30 +1549,32 @@ func (P *Parser) TryStatement() bool {
func (P *Parser) ParseImportSpec() { func (P *Parser) ParseImportSpec() {
P.Trace("ImportSpec"); P.Trace("ImportSpec");
var obj *Globals.Object = nil;
if P.tok == Scanner.PERIOD { if P.tok == Scanner.PERIOD {
P.Error(P.pos, `"import ." not yet handled properly`);
P.Next(); P.Next();
} else if P.tok == Scanner.IDENT { } else if P.tok == Scanner.IDENT {
P.Next(); obj = P.ParseIdentDecl(Object.PACKAGE);
} }
P.Expect(Scanner.STRING);
P.Ecart();
}
func (P *Parser) ParseImportDecl() { if (EnableSemanticTests && P.tok == Scanner.STRING) {
P.Trace("ImportDecl"); // TODO eventually the scanner should strip the quotes
pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
P.Expect(Scanner.IMPORT); imp := new(Import.Importer);
if P.tok == Scanner.LPAREN { pkg := imp.Import(P.comp, Utils.FixExt(Utils.BaseName(pkg_name)));
P.Next(); if pkg != nil {
for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF { if obj == nil {
P.ParseImportSpec(); // use original package name
P.Optional(Scanner.SEMICOLON); // TODO this seems wrong obj = pkg.obj;
P.Declare(obj);
}
obj.pnolev = pkg.obj.pnolev;
} else {
P.Error(P.pos, `import of "` + pkg_name + `" failed`);
} }
P.Next(); P.Next();
} else { } else {
P.ParseImportSpec(); P.Expect(Scanner.STRING); // use Expect() error handling
} }
P.Ecart(); P.Ecart();
...@@ -1569,6 +1659,7 @@ func (P *Parser) ParseVarSpec(exported bool) { ...@@ -1569,6 +1659,7 @@ func (P *Parser) ParseVarSpec(exported bool) {
// TODO With method variables, we wouldn't need this dispatch function. // TODO With method variables, we wouldn't need this dispatch function.
func (P *Parser) ParseSpec(exported bool, keyword int) { func (P *Parser) ParseSpec(exported bool, keyword int) {
switch keyword { switch keyword {
case Scanner.IMPORT: P.ParseImportSpec();
case Scanner.CONST: P.ParseConstSpec(exported); case Scanner.CONST: P.ParseConstSpec(exported);
case Scanner.TYPE: P.ParseTypeSpec(exported); case Scanner.TYPE: P.ParseTypeSpec(exported);
case Scanner.VAR: P.ParseVarSpec(exported); case Scanner.VAR: P.ParseVarSpec(exported);
...@@ -1586,7 +1677,8 @@ func (P *Parser) ParseDecl(exported bool, keyword int) { ...@@ -1586,7 +1677,8 @@ func (P *Parser) ParseDecl(exported bool, keyword int) {
for P.tok == Scanner.IDENT { for P.tok == Scanner.IDENT {
P.ParseSpec(exported, keyword); P.ParseSpec(exported, keyword);
if P.tok != Scanner.RPAREN { if P.tok != Scanner.RPAREN {
P.Expect(Scanner.SEMICOLON); // P.Expect(Scanner.SEMICOLON);
P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go)
} }
} }
P.Next(); P.Next();
...@@ -1602,12 +1694,13 @@ func (P *Parser) ParseFuncDecl(exported bool) { ...@@ -1602,12 +1694,13 @@ func (P *Parser) ParseFuncDecl(exported bool) {
P.Trace("FuncDecl"); P.Trace("FuncDecl");
P.Expect(Scanner.FUNC); P.Expect(Scanner.FUNC);
P.ParseNamedSignature(); ident, typ := P.ParseNamedSignature();
obj := P.DeclareFunc(exported, ident, typ); // need obj later for statements
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
// forward declaration // forward declaration
P.Next(); P.Next();
} else { } else {
P.ParseBlock(); P.ParseBlock(typ.scope);
} }
P.Ecart(); P.Ecart();
...@@ -1643,9 +1736,14 @@ func (P *Parser) ParseDeclaration() { ...@@ -1643,9 +1736,14 @@ func (P *Parser) ParseDeclaration() {
exported := false; exported := false;
if P.tok == Scanner.EXPORT { if P.tok == Scanner.EXPORT {
P.Next(); if P.level == 0 {
exported = true; exported = true;
} else {
P.Error(P.pos, "local declarations cannot be exported");
}
P.Next();
} }
switch P.tok { switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR: case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
P.ParseDecl(exported, P.tok); P.ParseDecl(exported, P.tok);
...@@ -1732,14 +1830,18 @@ func (P *Parser) ParseProgram() { ...@@ -1732,14 +1830,18 @@ func (P *Parser) ParseProgram() {
P.OpenScope(); P.OpenScope();
P.Expect(Scanner.PACKAGE); P.Expect(Scanner.PACKAGE);
pkg := P.comp.pkgs[0]; pkg := Globals.NewPackage(P.S.filename);
pkg.obj = P.ParseIdentDecl(Object.PACKAGE); pkg.obj = P.ParseIdentDecl(Object.PACKAGE);
P.comp.Insert(pkg);
if P.comp.npkgs != 1 {
panic "should have exactly one package now";
}
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
{ P.OpenScope(); { P.OpenScope();
pkg.scope = P.top_scope; pkg.scope = P.top_scope;
for P.tok == Scanner.IMPORT { for P.tok == Scanner.IMPORT {
P.ParseImportDecl(); P.ParseDecl(false, Scanner.IMPORT);
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
} }
......
// 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 Utils
export BaseName
func BaseName(s string) string {
// TODO this is not correct for non-ASCII strings!
i := len(s) - 1;
for i >= 0 && s[i] != '/' {
if s[i] > 128 {
panic "non-ASCII string"
}
i--;
}
return s[i + 1 : len(s)];
}
export FixExt
func FixExt(s string) string {
i := len(s) - 3; // 3 == len(".go");
if s[i : len(s)] == ".go" {
s = s[0 : i];
}
return s + ".7";
}
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