mirror of
https://github.com/golang/go
synced 2024-11-25 22:47:57 -07:00
- 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
This commit is contained in:
parent
ebec99179f
commit
4b0b7d8dfe
14
usr/gri/gosrc/base.go
Executable file
14
usr/gri/gosrc/base.go
Executable file
@ -0,0 +1,14 @@
|
||||
// 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 @@
|
||||
|
||||
package Compilation
|
||||
|
||||
import Utils "utils"
|
||||
import Globals "globals"
|
||||
import Object "object"
|
||||
import Type "type"
|
||||
@ -14,28 +15,6 @@ import Parser "parser"
|
||||
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
|
||||
func Compile(file_name string, verbose int) {
|
||||
src, ok := sys.readfile(file_name);
|
||||
@ -47,11 +26,6 @@ func Compile(file_name string, verbose int) {
|
||||
Universe.Init(); // TODO eventually this should be only needed once
|
||||
|
||||
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.Open(file_name, src);
|
||||
@ -66,8 +40,6 @@ func Compile(file_name string, verbose int) {
|
||||
}
|
||||
|
||||
// export
|
||||
/*
|
||||
exp := new(Export.Exporter);
|
||||
exp.Export(comp, FixExt(BaseName(file_name)));
|
||||
*/
|
||||
exp.Export(comp, Utils.FixExt(Utils.BaseName(file_name)));
|
||||
}
|
||||
|
123
usr/gri/gosrc/decls.go
Executable file
123
usr/gri/gosrc/decls.go
Executable file
@ -0,0 +1,123 @@
|
||||
// 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) {
|
||||
|
||||
|
||||
func (E *Exporter) WriteInt(x int) {
|
||||
/*
|
||||
if E.debug {
|
||||
print " #", x;
|
||||
}
|
||||
*/
|
||||
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) {
|
||||
if E.debug {
|
||||
print ` "`, s, `"`;
|
||||
}
|
||||
n := len(s);
|
||||
E.WriteInt(n);
|
||||
for i := 0; i < n; i++ {
|
||||
E.WriteByte(s[i]);
|
||||
}
|
||||
if E.debug {
|
||||
print ` "`, s, `"`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -68,14 +69,15 @@ func (E *Exporter) WriteObjTag(tag int) {
|
||||
if tag < 0 {
|
||||
panic "tag < 0";
|
||||
}
|
||||
E.WriteInt(tag);
|
||||
if E.debug {
|
||||
print "\nObj: ", tag; // obj kind
|
||||
}
|
||||
E.WriteInt(tag);
|
||||
}
|
||||
|
||||
|
||||
func (E *Exporter) WriteTypeTag(tag int) {
|
||||
E.WriteInt(tag);
|
||||
if E.debug {
|
||||
if tag > 0 {
|
||||
print "\nTyp ", E.type_ref, ": ", tag; // type form
|
||||
@ -83,11 +85,11 @@ func (E *Exporter) WriteTypeTag(tag int) {
|
||||
print " [Typ ", -tag, "]"; // type ref
|
||||
}
|
||||
}
|
||||
E.WriteInt(tag);
|
||||
}
|
||||
|
||||
|
||||
func (E *Exporter) WritePackageTag(tag int) {
|
||||
E.WriteInt(tag);
|
||||
if E.debug {
|
||||
if tag > 0 {
|
||||
print "\nPkg ", E.pkg_ref, ": ", tag; // package no
|
||||
@ -95,7 +97,6 @@ func (E *Exporter) WritePackageTag(tag int) {
|
||||
print " [Pkg ", -tag, "]"; // package ref
|
||||
}
|
||||
}
|
||||
E.WriteInt(tag);
|
||||
}
|
||||
|
||||
|
||||
@ -119,6 +120,7 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
E.WriteInt(n);
|
||||
|
||||
// export the objects, if any
|
||||
if n > 0 {
|
||||
@ -149,7 +151,7 @@ func (E *Exporter) WriteObject(obj *Globals.Object) {
|
||||
E.WriteObjTag(obj.kind);
|
||||
E.WriteString(obj.ident);
|
||||
E.WriteType(obj.typ);
|
||||
//E.WritePackage(E.comp.pkgs[obj.pnolev]);
|
||||
E.WritePackage(E.comp.pkgs[obj.pnolev]);
|
||||
|
||||
switch obj.kind {
|
||||
case Object.CONST:
|
||||
@ -249,16 +251,16 @@ func (E *Exporter) WritePackage(pkg *Globals.Package) {
|
||||
|
||||
|
||||
func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
|
||||
if E.debug {
|
||||
print "exporting to ", file_name;
|
||||
}
|
||||
|
||||
E.comp = comp;
|
||||
E.debug = true;
|
||||
E.debug = false;
|
||||
E.pos = 0;
|
||||
E.pkg_ref = 0;
|
||||
E.type_ref = 0;
|
||||
|
||||
if E.debug {
|
||||
print "exporting to ", file_name, "\n";
|
||||
}
|
||||
|
||||
// Predeclared types are "pre-exported".
|
||||
// TODO run the loop below only in debug mode
|
||||
{ i := 0;
|
||||
|
@ -280,6 +280,7 @@ func (C *Compilation) Insert(pkg *Package) {
|
||||
if C.Lookup(pkg.file_name) != nil {
|
||||
panic "package already inserted";
|
||||
}
|
||||
pkg.obj.pnolev = C.npkgs;
|
||||
C.pkgs[C.npkgs] = pkg;
|
||||
C.npkgs++;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import Type "type"
|
||||
import Universe "universe"
|
||||
|
||||
|
||||
export Importer // really only want to export Import()
|
||||
type Importer struct {
|
||||
comp *Globals.Compilation;
|
||||
debug bool;
|
||||
@ -257,6 +258,7 @@ func (I *Importer) ReadPackage() *Globals.Package {
|
||||
if pkg == nil {
|
||||
// new package
|
||||
pkg = Globals.NewPackage(file_name);
|
||||
pkg.obj = Globals.NewObject(-1, Object.PACKAGE, ident);
|
||||
pkg.scope = Globals.NewScope(nil);
|
||||
pkg = I.comp.InsertImport(pkg);
|
||||
|
||||
@ -271,24 +273,25 @@ func (I *Importer) ReadPackage() *Globals.Package {
|
||||
}
|
||||
|
||||
|
||||
func (I *Importer) Import(comp* Globals.Compilation, file_name string) {
|
||||
if I.debug {
|
||||
print "importing from ", file_name;
|
||||
}
|
||||
|
||||
buf, ok := sys.readfile(file_name);
|
||||
if !ok {
|
||||
panic "import failed";
|
||||
}
|
||||
|
||||
func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.Package {
|
||||
I.comp = comp;
|
||||
I.debug = true;
|
||||
I.buf = buf;
|
||||
I.debug = false;
|
||||
I.buf = "";
|
||||
I.pos = 0;
|
||||
I.npkgs = 0;
|
||||
I.ntypes = 0;
|
||||
|
||||
// Predeclared types are "pre-exported".
|
||||
if I.debug {
|
||||
print "importing from ", file_name, "\n";
|
||||
}
|
||||
|
||||
buf, ok := sys.readfile(file_name);
|
||||
if !ok {
|
||||
return nil;
|
||||
}
|
||||
I.buf = buf;
|
||||
|
||||
// Predeclared types are "pre-imported".
|
||||
for p := Universe.types.first; p != nil; p = p.next {
|
||||
if p.typ.ref != I.ntypes {
|
||||
panic "incorrect ref for predeclared type";
|
||||
@ -311,4 +314,6 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) {
|
||||
if I.debug {
|
||||
print "\n(", I.pos, " bytes)\n";
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
@ -4,11 +4,13 @@
|
||||
|
||||
package Parser
|
||||
|
||||
import Utils "utils"
|
||||
import Scanner "scanner"
|
||||
import Globals "globals"
|
||||
import Object "object"
|
||||
import Type "type"
|
||||
import Universe "universe"
|
||||
import Import "import"
|
||||
import AST "ast"
|
||||
|
||||
|
||||
@ -28,6 +30,7 @@ type Parser struct {
|
||||
val string; // token value (for IDENT, NUMBER, STRING only)
|
||||
|
||||
// Semantic analysis
|
||||
level int; // 0 = global scope, -1 = function scope of global functions, etc.
|
||||
top_scope *Globals.Scope;
|
||||
undef_types *Globals.List;
|
||||
exports *Globals.List;
|
||||
@ -77,6 +80,7 @@ func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int
|
||||
P.indent = 0;
|
||||
P.S = S;
|
||||
P.Next();
|
||||
P.level = 0;
|
||||
P.top_scope = Universe.scope;
|
||||
P.undef_types = Globals.NewList();
|
||||
P.exports = Globals.NewList();
|
||||
@ -128,7 +132,11 @@ func (P *Parser) Lookup(ident string) *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`);
|
||||
return; // don't insert it into the scope
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -225,10 +304,23 @@ func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
|
||||
}
|
||||
|
||||
if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
|
||||
panic "Qualified ident not complete yet";
|
||||
P.Next();
|
||||
P.ParseIdent();
|
||||
if obj.pnolev < 0 {
|
||||
panic "obj.pnolev < 0";
|
||||
}
|
||||
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();
|
||||
return obj;
|
||||
|
||||
@ -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
|
||||
//
|
||||
// (params)
|
||||
@ -424,9 +496,9 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type {
|
||||
|
||||
if P.tok == Scanner.PERIOD {
|
||||
p0 = sig.entries.len_;
|
||||
if (p0 != 1) {
|
||||
if (EnableSemanticTests && p0 != 1) {
|
||||
P.Error(recv_pos, "must have exactly one receiver")
|
||||
panic "UNIMPLEMENTED";
|
||||
panic "UNIMPLEMENTED (ParseAnonymousSignature)";
|
||||
// TODO do something useful here
|
||||
}
|
||||
P.Next();
|
||||
@ -462,10 +534,10 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
|
||||
recv_pos := P.pos;
|
||||
P.ParseParameters();
|
||||
p0 = sig.entries.len_;
|
||||
if (p0 != 1) {
|
||||
if (EnableSemanticTests && p0 != 1) {
|
||||
print "p0 = ", p0, "\n";
|
||||
P.Error(recv_pos, "must have exactly one receiver")
|
||||
panic "UNIMPLEMENTED";
|
||||
panic "UNIMPLEMENTED (ParseNamedSignature)";
|
||||
// TODO do something useful here
|
||||
}
|
||||
}
|
||||
@ -498,8 +570,13 @@ func (P *Parser) ParseMethodDecl() {
|
||||
P.Trace("MethodDecl");
|
||||
|
||||
P.ParseIdent();
|
||||
P.OpenScope();
|
||||
sig := P.top_scope;
|
||||
p0 := 0;
|
||||
P.ParseParameters();
|
||||
r0 := sig.entries.len_;
|
||||
P.TryResult();
|
||||
P.CloseScope();
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
|
||||
P.Ecart();
|
||||
@ -662,15 +739,26 @@ func (P *Parser) ParseStatementList() {
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseBlock() {
|
||||
func (P *Parser) ParseBlock(sig *Globals.Scope) {
|
||||
P.Trace("Block");
|
||||
|
||||
P.Expect(Scanner.LBRACE);
|
||||
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 {
|
||||
P.ParseStatementList();
|
||||
}
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
if sig != nil {
|
||||
P.level++;
|
||||
}
|
||||
P.CloseScope();
|
||||
P.Expect(Scanner.RBRACE);
|
||||
|
||||
@ -717,8 +805,8 @@ func (P *Parser) ParseNew() {
|
||||
func (P *Parser) ParseFunctionLit() {
|
||||
P.Trace("FunctionLit");
|
||||
|
||||
P.ParseFunctionType();
|
||||
P.ParseBlock();
|
||||
typ := P.ParseFunctionType();
|
||||
P.ParseBlock(typ.scope);
|
||||
|
||||
P.Ecart();
|
||||
}
|
||||
@ -1226,7 +1314,7 @@ func (P *Parser) ParseIfStat() *AST.IfStat {
|
||||
}
|
||||
}
|
||||
}
|
||||
P.ParseBlock();
|
||||
P.ParseBlock(nil);
|
||||
if P.tok == Scanner.ELSE {
|
||||
P.Next();
|
||||
if P.tok == Scanner.IF {
|
||||
@ -1262,7 +1350,7 @@ func (P *Parser) ParseForStat() {
|
||||
}
|
||||
}
|
||||
}
|
||||
P.ParseBlock();
|
||||
P.ParseBlock(nil);
|
||||
P.CloseScope();
|
||||
|
||||
P.Ecart();
|
||||
@ -1389,7 +1477,7 @@ func (P *Parser) ParseRangeStat() bool {
|
||||
P.ParseIdentList();
|
||||
P.Expect(Scanner.DEFINE);
|
||||
P.ParseExpression();
|
||||
P.ParseBlock();
|
||||
P.ParseBlock(nil);
|
||||
|
||||
P.Ecart();
|
||||
}
|
||||
@ -1431,7 +1519,7 @@ func (P *Parser) TryStatement() bool {
|
||||
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
|
||||
P.ParseControlFlowStat(P.tok);
|
||||
case Scanner.LBRACE:
|
||||
P.ParseBlock();
|
||||
P.ParseBlock(nil);
|
||||
case Scanner.IF:
|
||||
P.ParseIfStat();
|
||||
case Scanner.FOR:
|
||||
@ -1461,30 +1549,32 @@ func (P *Parser) TryStatement() bool {
|
||||
func (P *Parser) ParseImportSpec() {
|
||||
P.Trace("ImportSpec");
|
||||
|
||||
var obj *Globals.Object = nil;
|
||||
if P.tok == Scanner.PERIOD {
|
||||
P.Error(P.pos, `"import ." not yet handled properly`);
|
||||
P.Next();
|
||||
} else if P.tok == Scanner.IDENT {
|
||||
P.Next();
|
||||
obj = P.ParseIdentDecl(Object.PACKAGE);
|
||||
}
|
||||
P.Expect(Scanner.STRING);
|
||||
|
||||
P.Ecart();
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseImportDecl() {
|
||||
P.Trace("ImportDecl");
|
||||
|
||||
P.Expect(Scanner.IMPORT);
|
||||
if P.tok == Scanner.LPAREN {
|
||||
P.Next();
|
||||
for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
|
||||
P.ParseImportSpec();
|
||||
P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
|
||||
if (EnableSemanticTests && P.tok == Scanner.STRING) {
|
||||
// TODO eventually the scanner should strip the quotes
|
||||
pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
|
||||
imp := new(Import.Importer);
|
||||
pkg := imp.Import(P.comp, Utils.FixExt(Utils.BaseName(pkg_name)));
|
||||
if pkg != nil {
|
||||
if obj == nil {
|
||||
// use original package name
|
||||
obj = pkg.obj;
|
||||
P.Declare(obj);
|
||||
}
|
||||
obj.pnolev = pkg.obj.pnolev;
|
||||
} else {
|
||||
P.Error(P.pos, `import of "` + pkg_name + `" failed`);
|
||||
}
|
||||
P.Next();
|
||||
} else {
|
||||
P.ParseImportSpec();
|
||||
P.Expect(Scanner.STRING); // use Expect() error handling
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
@ -1569,6 +1659,7 @@ func (P *Parser) ParseVarSpec(exported bool) {
|
||||
// TODO With method variables, we wouldn't need this dispatch function.
|
||||
func (P *Parser) ParseSpec(exported bool, keyword int) {
|
||||
switch keyword {
|
||||
case Scanner.IMPORT: P.ParseImportSpec();
|
||||
case Scanner.CONST: P.ParseConstSpec(exported);
|
||||
case Scanner.TYPE: P.ParseTypeSpec(exported);
|
||||
case Scanner.VAR: P.ParseVarSpec(exported);
|
||||
@ -1586,7 +1677,8 @@ func (P *Parser) ParseDecl(exported bool, keyword int) {
|
||||
for P.tok == Scanner.IDENT {
|
||||
P.ParseSpec(exported, keyword);
|
||||
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();
|
||||
@ -1602,12 +1694,13 @@ func (P *Parser) ParseFuncDecl(exported bool) {
|
||||
P.Trace("FuncDecl");
|
||||
|
||||
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 {
|
||||
// forward declaration
|
||||
P.Next();
|
||||
} else {
|
||||
P.ParseBlock();
|
||||
P.ParseBlock(typ.scope);
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
@ -1643,9 +1736,14 @@ func (P *Parser) ParseDeclaration() {
|
||||
|
||||
exported := false;
|
||||
if P.tok == Scanner.EXPORT {
|
||||
if P.level == 0 {
|
||||
exported = true;
|
||||
} else {
|
||||
P.Error(P.pos, "local declarations cannot be exported");
|
||||
}
|
||||
P.Next();
|
||||
exported = true;
|
||||
}
|
||||
|
||||
switch P.tok {
|
||||
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
|
||||
P.ParseDecl(exported, P.tok);
|
||||
@ -1732,14 +1830,18 @@ func (P *Parser) ParseProgram() {
|
||||
|
||||
P.OpenScope();
|
||||
P.Expect(Scanner.PACKAGE);
|
||||
pkg := P.comp.pkgs[0];
|
||||
pkg := Globals.NewPackage(P.S.filename);
|
||||
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.OpenScope();
|
||||
pkg.scope = P.top_scope;
|
||||
for P.tok == Scanner.IMPORT {
|
||||
P.ParseImportDecl();
|
||||
P.ParseDecl(false, Scanner.IMPORT);
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
}
|
||||
|
||||
|
29
usr/gri/gosrc/utils.go
Normal file
29
usr/gri/gosrc/utils.go
Normal file
@ -0,0 +1,29 @@
|
||||
// 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";
|
||||
}
|
Loading…
Reference in New Issue
Block a user