- added more code (package, export, compilation)

- first cut at semantic checks (disabled)

SVN=127348
This commit is contained in:
Robert Griesemer 2008-07-15 15:37:14 -07:00
parent 1401c11008
commit a6f87794ff
7 changed files with 597 additions and 65 deletions

View File

@ -0,0 +1,52 @@
// 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 Globals "globals"
import Object "object"
import Type "type"
import Package "package"
import Scanner "scanner"
import Parser "parser"
export Compilation
type Compilation struct {
src_name string;
pkg *Globals.Object;
imports *Globals.List; // a list of *Globals.Package
}
func (C *Compilation) Lookup(pkg_name string) *Package.Package {
panic "UNIMPLEMENTED";
return nil;
}
func (C *Compilation) Insert(pkg *Package.Package) {
panic "UNIMPLEMENTED";
}
func (C *Compilation) InsertImport(pkg *Package.Package) *Package.Package {
panic "UNIMPLEMENTED";
return nil;
}
func (C *Compilation) Import(pkg_name string) (pno int) {
panic "UNIMPLEMENTED";
}
func (C *Compilation) Export() {
panic "UNIMPLEMENTED";
}
export Compile
func Compile() {
}

302
usr/gri/gosrc/export.go Executable file
View File

@ -0,0 +1,302 @@
// 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 Globals "globals"
import Object "object"
import Type "type"
import Package "package"
type Exporter struct {
/*
Compilation* comp;
*/
debug bool;
buf [4*1024] byte;
pos int;
pkg_ref int;
type_ref int;
};
func (E *Exporter) WriteType(typ *Globals.Type);
func (E *Exporter) WriteObject(obj *Globals.Object);
func (E *Exporter) WritePackage(pkg *Package.Package) ;
func (E *Exporter) WriteByte(x byte) {
E.buf[E.pos] = x;
E.pos++;
if E.debug {
print " ", x;
}
}
func (E *Exporter) WriteInt(x int) {
if E.debug {
print " #", 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));
}
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]);
}
}
func (E *Exporter) WriteObjTag(tag int) {
if tag < 0 {
panic "tag < 0";
}
if E.debug {
print "\nO: ", tag; // obj kind
}
E.WriteInt(tag);
}
func (E *Exporter) WriteTypeTag(tag int) {
if E.debug {
if tag > 0 {
print "\nT", E.type_ref, ": ", tag; // type form
} else {
print " [T", -tag, "]"; // type ref
}
}
E.WriteInt(tag);
}
func (E *Exporter) WritePackageTag(tag int) {
if E.debug {
if tag > 0 {
print "\nP", E.pkg_ref, ": ", tag; // package no
} else {
print " [P", -tag, "]"; // package ref
}
}
E.WriteInt(tag);
}
func (E *Exporter) WriteTypeField(fld *Globals.Object) {
if fld.kind != Object.VAR {
panic "fld.kind != Object.VAR";
}
E.WriteType(fld.typ);
}
func (E *Exporter) WriteScope(scope *Globals.Scope) {
if E.debug {
print " {";
}
// determine number of objects to export
n := 0;
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.mark {
n++;
}
}
// export the objects, if any
if n > 0 {
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.mark {
E.WriteObject(p.obj);
}
}
}
if E.debug {
print " }";
}
}
func (E *Exporter) WriteObject(obj *Globals.Object) {
if obj == nil || !obj.mark {
panic "obj == nil || !obj.mark";
}
if obj.kind == Object.TYPE && obj.typ.obj == obj {
// primary type object - handled entirely by WriteType()
E.WriteObjTag(Object.PTYPE);
E.WriteType(obj.typ);
} else {
E.WriteObjTag(obj.kind);
E.WriteString(obj.ident);
E.WriteType(obj.typ);
panic "UNIMPLEMENTED";
//E.WritePackage(E.comp.packages[obj.pnolev]);
switch obj.kind {
case Object.BAD: fallthrough;
case Object.PACKAGE: fallthrough;
case Object.PTYPE:
panic "UNREACHABLE";
case Object.CONST:
E.WriteInt(0); // should be the correct value
break;
case Object.TYPE:
// nothing to do
case Object.VAR:
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) WriteType(typ *Globals.Type) {
if typ == nil {
panic "typ == nil";
}
if typ.ref >= 0 {
E.WriteTypeTag(-typ.ref); // type already exported
return;
}
if typ.form <= 0 {
panic "typ.form <= 0";
}
E.WriteTypeTag(typ.form);
typ.ref = E.type_ref;
E.type_ref++;
if typ.obj != nil {
if typ.obj.typ != typ {
panic "typ.obj.type() != typ"; // primary type
}
E.WriteString(typ.obj.ident);
panic "UNIMPLEMENTED";
//WritePackage(E.comp.packages[typ.obj.pnolev]);
} else {
E.WriteString("");
}
switch typ.form {
case Type.UNDEF: fallthrough;
case Type.BAD: fallthrough;
case Type.NIL: fallthrough;
case Type.BOOL: fallthrough;
case Type.UINT: fallthrough;
case Type.INT: fallthrough;
case Type.FLOAT: fallthrough;
case Type.STRING: fallthrough;
case Type.ANY:
panic "UNREACHABLE";
case Type.ARRAY:
E.WriteInt(typ.len_);
E.WriteTypeField(typ.elt);
case Type.MAP:
E.WriteTypeField(typ.key);
E.WriteTypeField(typ.elt);
case Type.CHANNEL:
E.WriteInt(typ.flags);
E.WriteTypeField(typ.elt);
case Type.FUNCTION:
E.WriteInt(typ.flags);
fallthrough;
case Type.STRUCT: fallthrough;
case Type.INTERFACE:
E.WriteScope(typ.scope);
case Type.POINTER: fallthrough;
case Type.REFERENCE:
E.WriteTypeField(typ.elt);
default:
panic "UNREACHABLE";
}
}
func (E *Exporter) WritePackage(pkg *Package.Package) {
if pkg.ref >= 0 {
E.WritePackageTag(-pkg.ref); // package already exported
return;
}
if Object.PACKAGE <= 0 {
panic "Object.PACKAGE <= 0";
}
E.WritePackageTag(Object.PACKAGE);
pkg.ref = E.pkg_ref;
E.pkg_ref++;
E.WriteString(pkg.ident);
E.WriteString(pkg.path);
E.WriteString(pkg.key);
}
func (E *Exporter) Export(/*Compilation* comp, BBuffer* buf*/) {
panic "UNIMPLEMENTED";
/*
E.comp = comp;
E.buf = buf;
E.pak_ref = 0;
E.nbytes = 0;
*/
// Predeclared types are "pre-exported".
/*
#ifdef DEBUG
for (int i = 0; i < Universe.types.len(); i++) {
ASSERT(Universe.types[i].ref == i);
}
#endif
E.type_ref = Universe.types.len();
*/
var pkg *Package.Package = nil; // comp.packages[0];
E.WritePackage(pkg);
for p := pkg.scope.entries.first; p != nil; p = p.next {
if p.obj.mark {
E.WriteObject(p.obj);
}
}
E.WriteObjTag(0);
if E.debug {
print "\n(", E.pos, ")\n";
}
}
export Export
func Export(/*Compilation* comp, BBuffer* buf*/) {
/*
Exporter exp;
exp.Export(comp, buf);
*/
}

View File

@ -16,6 +16,7 @@ package Globals
export Object export Object
type Object struct { type Object struct {
mark bool; // mark => object marked for export mark bool; // mark => object marked for export
pos int; // source position
kind int; kind int;
ident string; ident string;
typ *Type; typ *Type;
@ -67,9 +68,10 @@ type Scope struct {
// Creation // Creation
export NewObject export NewObject
func NewObject(kind int, ident string) *Object { func NewObject(pos, kind int, ident string) *Object {
obj := new(Object); obj := new(Object);
obj.mark = false; obj.mark = false;
obj.pos = pos;
obj.kind = kind; obj.kind = kind;
obj.ident = ident; obj.ident = ident;
obj.typ = nil; // Universe::undef_t; obj.typ = nil; // Universe::undef_t;

View File

@ -7,7 +7,7 @@ package Object
import Globals "globals" import Globals "globals"
export BAD, CONST, TYPE, VAR, FUNC, PACKAGE export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, PTYPE
const /* kind */ ( const /* kind */ (
BAD = iota; // error handling BAD = iota; // error handling
CONST; TYPE; VAR; FUNC; PACKAGE; CONST; TYPE; VAR; FUNC; PACKAGE;

23
usr/gri/gosrc/package.go Normal file
View File

@ -0,0 +1,23 @@
// 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 Package
import Globals "globals"
export Package
type Package struct {
ref int;
ident string;
path string;
key string;
scope *Globals.Scope;
}
export NewPackage;
func NewPackage() *Package {
pkg := new(Package);
return pkg;
}

View File

@ -6,9 +6,15 @@ package Parser
import Scanner "scanner" import Scanner "scanner"
import Globals "globals" import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe" import Universe "universe"
// So I can submit and have a running parser for now...
const EnableSemanticTests = false;
export Parser export Parser
type Parser struct { type Parser struct {
verbose, indent int; verbose, indent int;
@ -20,6 +26,9 @@ type Parser struct {
} }
// ----------------------------------------------------------------------------
// Support functions
func (P *Parser) PrintIndent() { func (P *Parser) PrintIndent() {
for i := P.indent; i > 0; i-- { for i := P.indent; i > 0; i-- {
print ". "; print ". ";
@ -52,7 +61,7 @@ func (P *Parser) Next() {
} }
if P.verbose > 1 { if P.verbose > 1 {
P.PrintIndent(); P.PrintIndent();
print Scanner.TokenName(P.tok), "\n"; print "[", P.beg, "] ", Scanner.TokenName(P.tok), "\n";
} }
} }
@ -68,16 +77,14 @@ func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
func (P *Parser) Error(pos int, msg string) { func (P *Parser) Error(pos int, msg string) {
P.S.Error(pos, msg); P.S.Error(pos, msg);
P.Next(); // make progress
} }
func (P *Parser) Expect(tok int) { func (P *Parser) Expect(tok int) {
if P.tok == tok { if P.tok != tok {
P.Next()
} else {
P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'"); P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
} }
P.Next(); // make progress in any case
} }
@ -89,6 +96,7 @@ func (P *Parser) Optional(tok int) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scopes
func (P *Parser) OpenScope() { func (P *Parser) OpenScope() {
P.top_scope = Globals.NewScope(P.top_scope); P.top_scope = Globals.NewScope(P.top_scope);
@ -112,9 +120,13 @@ 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 {
return;
}
if scope.Lookup(obj.ident) != nil { if scope.Lookup(obj.ident) != nil {
// TODO is this the correct error position? // TODO is this the correct error position?
P.Error(P.beg, `"` + 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
} }
scope.Insert(obj); scope.Insert(obj);
@ -130,18 +142,56 @@ func (P *Parser) Declare(obj *Globals.Object) {
// Common productions // Common productions
func (P *Parser) TryType() bool; func (P *Parser) TryType() *Globals.Type;
func (P *Parser) ParseExpression(); func (P *Parser) ParseExpression();
func (P *Parser) TryStatement() bool; func (P *Parser) TryStatement() bool;
func (P *Parser) ParseDeclaration(); func (P *Parser) ParseDeclaration();
func (P *Parser) ParseIdent() { func (P *Parser) ParseIdent() string {
if P.verbose > 0 { P.Trace("Ident");
P.PrintIndent();
print "Ident = \"", P.ident, "\"\n"; ident := "";
if P.tok == Scanner.IDENT {
ident = P.ident;
if P.verbose > 0 {
P.PrintIndent();
print "Ident = \"", ident, "\"\n";
}
P.Next();
} else {
P.Expect(Scanner.IDENT); // use Expect() error handling
} }
P.Expect(Scanner.IDENT);
P.Ecart();
return ident;
}
func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
P.Trace("IdentDecl");
pos := P.beg;
obj := Globals.NewObject(pos, kind, P.ParseIdent());
P.Declare(obj);
P.Ecart();
return obj;
}
func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
P.Trace("IdentDeclList");
list := Globals.NewList();
list.AddObj(P.ParseIdentDecl(kind));
for P.tok == Scanner.COMMA {
P.Next();
list.AddObj(P.ParseIdentDecl(kind));
}
P.Ecart();
return list;
} }
@ -156,37 +206,76 @@ func (P *Parser) ParseIdentList() {
} }
func (P *Parser) ParseQualifiedIdent() { func (P *Parser) ParseQualifiedIdent() *Globals.Object {
P.Trace("QualifiedIdent"); P.Trace("QualifiedIdent");
P.ParseIdent();
if P.tok == Scanner.PERIOD { if EnableSemanticTests {
P.Next(); pos := P.beg;
ident := P.ParseIdent();
obj := P.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared`);
obj = Globals.NewObject(pos, Object.BAD, ident);
}
if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
panic "Qualified ident not complete yet";
P.Next();
P.ParseIdent();
}
P.Ecart();
return obj;
} else {
P.ParseIdent(); P.ParseIdent();
if P.tok == Scanner.PERIOD {
P.Next();
P.ParseIdent();
}
P.Ecart();
return nil;
} }
P.Ecart();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Types // Types
func (P *Parser) ParseType() { func (P *Parser) ParseType() *Globals.Type{
P.Trace("Type"); P.Trace("Type");
if !P.TryType() {
typ := P.TryType();
if typ == nil {
P.Error(P.beg, "type expected"); P.Error(P.beg, "type expected");
typ = Universe.bad_t;
} }
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParseTypeName() { func (P *Parser) ParseTypeName() *Globals.Type {
P.Trace("TypeName"); P.Trace("TypeName");
P.ParseQualifiedIdent();
P.Ecart(); if EnableSemanticTests {
obj := P.ParseQualifiedIdent();
typ := obj.typ;
if obj.kind != Object.TYPE {
P.Error(obj.pos, `"` + obj.ident + `" is not a type`);
typ = Universe.bad_t;
}
P.Ecart();
return typ;
} else {
P.ParseQualifiedIdent();
P.Ecart();
return Universe.bad_t;
}
} }
func (P *Parser) ParseArrayType() { func (P *Parser) ParseArrayType() *Globals.Type {
P.Trace("ArrayType"); P.Trace("ArrayType");
P.Expect(Scanner.LBRACK); P.Expect(Scanner.LBRACK);
if P.tok != Scanner.RBRACK { if P.tok != Scanner.RBRACK {
@ -195,10 +284,11 @@ func (P *Parser) ParseArrayType() {
P.Expect(Scanner.RBRACK); P.Expect(Scanner.RBRACK);
P.ParseType(); P.ParseType();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
func (P *Parser) ParseChannelType() { func (P *Parser) ParseChannelType() *Globals.Type {
P.Trace("ChannelType"); P.Trace("ChannelType");
P.Expect(Scanner.CHAN); P.Expect(Scanner.CHAN);
switch P.tok { switch P.tok {
@ -208,6 +298,7 @@ func (P *Parser) ParseChannelType() {
} }
P.ParseType(); P.ParseType();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
@ -249,7 +340,7 @@ func (P *Parser) TryResult() bool {
P.ParseParameters(); P.ParseParameters();
res = true; res = true;
} else { } else {
res = P.TryType(); res = P.TryType() != nil;
} }
P.Ecart(); P.Ecart();
return res; return res;
@ -302,11 +393,12 @@ func (P *Parser) ParseNamedSignature() {
} }
func (P *Parser) ParseFunctionType() { func (P *Parser) ParseFunctionType() *Globals.Type {
P.Trace("FunctionType"); P.Trace("FunctionType");
P.Expect(Scanner.FUNC); P.Expect(Scanner.FUNC);
P.ParseAnonymousSignature(); P.ParseAnonymousSignature();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
@ -320,7 +412,7 @@ func (P *Parser) ParseMethodDecl() {
} }
func (P *Parser) ParseInterfaceType() { func (P *Parser) ParseInterfaceType() *Globals.Type {
P.Trace("InterfaceType"); P.Trace("InterfaceType");
P.Expect(Scanner.INTERFACE); P.Expect(Scanner.INTERFACE);
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
@ -331,10 +423,11 @@ func (P *Parser) ParseInterfaceType() {
P.CloseScope(); P.CloseScope();
P.Next(); P.Next();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
func (P *Parser) ParseMapType() { func (P *Parser) ParseMapType() *Globals.Type {
P.Trace("MapType"); P.Trace("MapType");
P.Expect(Scanner.MAP); P.Expect(Scanner.MAP);
P.Expect(Scanner.LBRACK); P.Expect(Scanner.LBRACK);
@ -342,23 +435,32 @@ func (P *Parser) ParseMapType() {
P.Expect(Scanner.RBRACK); P.Expect(Scanner.RBRACK);
P.ParseType(); P.ParseType();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
func (P *Parser) ParseFieldDecl() { func (P *Parser) ParseFieldDecl() {
P.Trace("FieldDecl"); P.Trace("FieldDecl");
P.ParseIdentList();
P.ParseType(); list := P.ParseIdentDeclList(Object.VAR);
typ := P.ParseType(); // TODO should check completeness of types
for p := list.first; p != nil; p = p.next {
p.obj.typ = typ; // TODO should use/have set_type()
}
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseStructType() { func (P *Parser) ParseStructType() *Globals.Type {
P.Trace("StructType"); P.Trace("StructType");
P.Expect(Scanner.STRUCT); P.Expect(Scanner.STRUCT);
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
P.OpenScope(); P.OpenScope();
for P.tok != Scanner.RBRACE { typ := Globals.NewType(Type.STRUCT);
typ.scope = P.top_scope;
for P.tok == Scanner.IDENT {
P.ParseFieldDecl(); P.ParseFieldDecl();
if P.tok != Scanner.RBRACE { if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON); P.Expect(Scanner.SEMICOLON);
@ -367,43 +469,39 @@ func (P *Parser) ParseStructType() {
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
P.CloseScope(); P.CloseScope();
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParsePointerType() { func (P *Parser) ParsePointerType() *Globals.Type {
P.Trace("PointerType"); P.Trace("PointerType");
P.Expect(Scanner.MUL); P.Expect(Scanner.MUL);
P.ParseType(); P.ParseType();
P.Ecart(); P.Ecart();
return Universe.bad_t;
} }
func (P *Parser) TryType() bool { // Returns nil if no type was found.
func (P *Parser) TryType() *Globals.Type {
P.Trace("Type (try)"); P.Trace("Type (try)");
var typ *Globals.Type = nil;
switch P.tok { switch P.tok {
case Scanner.IDENT: case Scanner.IDENT: typ = P.ParseTypeName();
P.ParseTypeName(); case Scanner.LBRACK: typ = P.ParseArrayType();
case Scanner.LBRACK: case Scanner.CHAN: typ = P.ParseChannelType();
P.ParseArrayType(); case Scanner.INTERFACE: typ = P.ParseInterfaceType();
case Scanner.CHAN: case Scanner.FUNC: typ = P.ParseFunctionType();
P.ParseChannelType(); case Scanner.MAP: typ = P.ParseMapType();
case Scanner.INTERFACE: case Scanner.STRUCT: typ = P.ParseStructType();
P.ParseInterfaceType(); case Scanner.MUL: typ = P.ParsePointerType();
case Scanner.FUNC:
P.ParseFunctionType();
case Scanner.MAP:
P.ParseMapType();
case Scanner.STRUCT:
P.ParseStructType();
case Scanner.MUL:
P.ParsePointerType();
default:
P.Ecart();
return false;
} }
P.Ecart(); P.Ecart();
return true; return typ;
} }
@ -414,6 +512,7 @@ func (P *Parser) ParseStatement() {
P.Trace("Statement"); P.Trace("Statement");
if !P.TryStatement() { if !P.TryStatement() {
P.Error(P.beg, "statement expected"); P.Error(P.beg, "statement expected");
P.Next(); // make progress
} }
P.Ecart(); P.Ecart();
} }
@ -500,6 +599,7 @@ func (P *Parser) ParseOperand() {
P.ParseNew(); P.ParseNew();
default: default:
P.Error(P.beg, "operand expected"); P.Error(P.beg, "operand expected");
P.Next(); // make progress
} }
P.Ecart(); P.Ecart();
} }
@ -903,8 +1003,9 @@ func (P *Parser) TryStatement() bool {
case Scanner.FUNC: case Scanner.FUNC:
// for now we do not allow local function declarations // for now we do not allow local function declarations
fallthrough; fallthrough;
case Scanner.LSS: fallthrough;
case Scanner.GTR: case Scanner.GTR:
P.ParseSimpleStat(); // send P.ParseSimpleStat(); // send or receive
case Scanner.IDENT: case Scanner.IDENT:
switch P.ident { switch P.ident {
case "print", "panic": case "print", "panic":
@ -947,18 +1048,21 @@ func (P *Parser) TryStatement() bool {
func (P *Parser) ParseImportSpec() { func (P *Parser) ParseImportSpec() {
P.Trace("ImportSpec"); P.Trace("ImportSpec");
if P.tok == Scanner.PERIOD { if P.tok == Scanner.PERIOD {
P.Next(); P.Next();
} else if P.tok == Scanner.IDENT { } else if P.tok == Scanner.IDENT {
P.Next(); P.Next();
} }
P.Expect(Scanner.STRING); P.Expect(Scanner.STRING);
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseImportDecl() { func (P *Parser) ParseImportDecl() {
P.Trace("ImportDecl"); P.Trace("ImportDecl");
P.Expect(Scanner.IMPORT); P.Expect(Scanner.IMPORT);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
@ -970,24 +1074,33 @@ func (P *Parser) ParseImportDecl() {
} else { } else {
P.ParseImportSpec(); P.ParseImportSpec();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseConstSpec() { func (P *Parser) ParseConstSpec() {
P.Trace("ConstSpec"); P.Trace("ConstSpec");
P.ParseIdent();
P.TryType(); list := P.ParseIdentDeclList(Object.CONST);
typ := P.TryType();
if typ != nil {
for p := list.first; p != nil; p = p.next {
p.obj.typ = typ; // TODO should use/have set_type()!
}
}
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpression(); P.ParseExpressionList();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseConstDecl() { func (P *Parser) ParseConstDecl() {
P.Trace("ConstDecl"); P.Trace("ConstDecl");
P.Expect(Scanner.CONST); P.Expect(Scanner.CONST);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
@ -1001,20 +1114,45 @@ func (P *Parser) ParseConstDecl() {
} else { } else {
P.ParseConstSpec(); P.ParseConstSpec();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseTypeSpec() { func (P *Parser) ParseTypeSpec() {
P.Trace("TypeSpec"); P.Trace("TypeSpec");
P.ParseIdent();
P.TryType(); pos := P.beg;
ident := P.ParseIdent();
obj := P.top_scope.Lookup(ident); // only lookup in top scope!
if obj != nil {
// ok if forward declared type
if obj.kind != Object.TYPE || obj.typ.form != Type.UNDEF {
// TODO use obj.pos to refer to decl pos in error msg!
P.Error(pos, `"` + ident + `" is declared already`);
}
} else {
obj = Globals.NewObject(pos, Object.TYPE, ident);
obj.typ = Universe.undef_t; // TODO fix this
P.top_scope.Insert(obj);
}
typ := P.TryType(); // no type if we have a forward decl
if typ != nil {
// TODO what about the name of incomplete types?
obj.typ = typ; // TODO should use/have set_typ()!
if typ.obj == nil {
typ.obj = obj; // primary type object
}
}
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseTypeDecl() { func (P *Parser) ParseTypeDecl() {
P.Trace("TypeDecl"); P.Trace("TypeDecl");
P.Expect(Scanner.TYPE); P.Expect(Scanner.TYPE);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
@ -1028,29 +1166,36 @@ func (P *Parser) ParseTypeDecl() {
} else { } else {
P.ParseTypeSpec(); P.ParseTypeSpec();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseVarSpec() { func (P *Parser) ParseVarSpec() {
P.Trace("VarSpec"); P.Trace("VarSpec");
P.ParseIdentList();
list := P.ParseIdentDeclList(Object.VAR);
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); P.ParseExpressionList();
} else { } else {
P.ParseType(); typ := P.ParseType();
for p := list.first; p != nil; p = p.next {
p.obj.typ = typ; // TODO should use/have set_type()!
}
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); P.ParseExpressionList();
} }
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseVarDecl() { func (P *Parser) ParseVarDecl() {
P.Trace("VarDecl"); P.Trace("VarDecl");
P.Expect(Scanner.VAR); P.Expect(Scanner.VAR);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
@ -1064,12 +1209,14 @@ func (P *Parser) ParseVarDecl() {
} else { } else {
P.ParseVarSpec(); P.ParseVarSpec();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseFuncDecl() { func (P *Parser) ParseFuncDecl() {
P.Trace("FuncDecl"); P.Trace("FuncDecl");
P.Expect(Scanner.FUNC); P.Expect(Scanner.FUNC);
P.ParseNamedSignature(); P.ParseNamedSignature();
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
@ -1078,12 +1225,14 @@ func (P *Parser) ParseFuncDecl() {
} else { } else {
P.ParseBlock(); P.ParseBlock();
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseExportDecl() { func (P *Parser) ParseExportDecl() {
P.Trace("ExportDecl"); P.Trace("ExportDecl");
P.Expect(Scanner.EXPORT); P.Expect(Scanner.EXPORT);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
@ -1099,12 +1248,14 @@ func (P *Parser) ParseExportDecl() {
P.ParseIdent(); P.ParseIdent();
} }
} }
P.Ecart(); P.Ecart();
} }
func (P *Parser) ParseDeclaration() { func (P *Parser) ParseDeclaration() {
P.Trace("Declaration"); P.Trace("Declaration");
indent := P.indent; indent := P.indent;
switch P.tok { switch P.tok {
case Scanner.CONST: case Scanner.CONST:
@ -1119,10 +1270,12 @@ func (P *Parser) ParseDeclaration() {
P.ParseExportDecl(); P.ParseExportDecl();
default: default:
P.Error(P.beg, "declaration expected"); P.Error(P.beg, "declaration expected");
P.Next(); // make progress
} }
if indent != P.indent { if indent != P.indent {
panic "imbalanced tracing code" panic "imbalanced tracing code"
} }
P.Ecart(); P.Ecart();
} }

View File

@ -67,7 +67,7 @@ var (
func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object { func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object {
obj := Globals.NewObject(kind, ident); obj := Globals.NewObject(-1 /* no source pos */, kind, ident);
obj.typ = typ; obj.typ = typ;
if kind == Object.TYPE && typ.obj == nil { if kind == Object.TYPE && typ.obj == nil {
typ.obj = obj; // set primary type object typ.obj = obj; // set primary type object