Commit 1f465139 authored by Robert Griesemer's avatar Robert Griesemer

various fixes:

- missing return in import code
- proper propagation of flags to various components
- better error message when source position is missing
- cleanups

R=r
OCL=13676
CL=13676
parent 0748bf37
......@@ -17,22 +17,18 @@ import Printer "printer"
export Compile
func Compile(file_name string, verbose int) {
func Compile(comp *Globals.Compilation, file_name string) {
src, ok := sys.readfile(file_name);
if !ok {
print "cannot open ", file_name, "\n"
return;
}
Universe.Init(); // TODO eventually this should be only needed once
comp := Globals.NewCompilation();
scanner := new(Scanner.Scanner);
scanner.Open(file_name, src);
parser := new(Parser.Parser);
parser.Open(comp, scanner, verbose);
parser.Open(comp, scanner);
print "parsing ", file_name, "\n";
parser.ParseProgram();
......@@ -40,12 +36,9 @@ func Compile(file_name string, verbose int) {
return;
}
/*
// export
exp := new(Export.Exporter);
exp.Export(comp, Utils.FixExt(Utils.BaseName(file_name)));
// print export
Printer.PrintObject(comp, comp.pkgs[0].obj, false);
*/
if comp.flags.semantic_checks {
Printer.PrintObject(comp, comp.pkgs[0].obj, false);
Export.Export(comp, file_name);
}
}
......@@ -121,4 +121,4 @@ func (p *T4) m5(a, b int, c float) (z T5, ok bool) {
export c0, c1, v2, v3
export T0, T1, T4, T4, T4, M0, M5, I2, f0, f1
// export Node0, Node1 // this fails
export Node0, Node1
......@@ -4,13 +4,13 @@
package Exporter
import Utils "utils"
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
export Exporter // really only want to export Export()
type Exporter struct {
comp *Globals.Compilation;
debug bool;
......@@ -65,7 +65,7 @@ func (E *Exporter) WriteString(s string) {
}
func (E *Exporter) WriteObjTag(tag int) {
func (E *Exporter) WriteObjectTag(tag int) {
if tag < 0 {
panic "tag < 0";
}
......@@ -113,24 +113,13 @@ func (E *Exporter) WriteScope(scope *Globals.Scope) {
print " {";
}
// determine number of objects to export
n := 0;
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.exported {
n++;
}
}
E.WriteInt(n);
// export the objects, if any
if n > 0 {
for p := scope.entries.first; p != nil; p = p.next {
if p.obj.exported {
E.WriteObject(p.obj);
}
E.WriteObject(p.obj);
}
}
E.WriteObjectTag(0); // terminator
if E.debug {
print " }";
}
......@@ -144,11 +133,11 @@ func (E *Exporter) WriteObject(obj *Globals.Object) {
if obj.kind == Object.TYPE && obj.typ.obj == obj {
// primary type object - handled entirely by WriteType()
E.WriteObjTag(Object.PTYPE);
E.WriteObjectTag(Object.PTYPE);
E.WriteType(obj.typ);
} else {
E.WriteObjTag(obj.kind);
E.WriteObjectTag(obj.kind);
E.WriteString(obj.ident);
E.WriteType(obj.typ);
E.WritePackage(E.comp.pkgs[obj.pnolev]);
......@@ -252,7 +241,7 @@ func (E *Exporter) WritePackage(pkg *Globals.Package) {
func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
E.comp = comp;
E.debug = false;
E.debug = comp.flags.debug;
E.pos = 0;
E.pkg_ref = 0;
E.type_ref = 0;
......@@ -275,13 +264,8 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
pkg := comp.pkgs[0];
E.WritePackage(pkg);
for p := pkg.scope.entries.first; p != nil; p = p.next {
if p.obj.exported {
E.WriteObject(p.obj);
}
}
E.WriteObjTag(0);
E.WriteScope(pkg.scope);
if E.debug {
print "\n(", E.pos, " bytes)\n";
}
......@@ -293,3 +277,10 @@ func (E *Exporter) Export(comp* Globals.Compilation, file_name string) {
panic "export failed";
}
}
export Export
func Export(comp* Globals.Compilation, pkg_name string) {
var E Exporter;
(&E).Export(comp, Utils.FixExt(Utils.BaseName(pkg_name)));
}
......@@ -75,8 +75,17 @@ type Scope struct {
}
export Flags;
type Flags struct {
debug bool;
semantic_checks bool;
verbose int;
}
export Compilation
type Compilation struct {
flags *Flags;
// TODO use open arrays eventually
pkgs [256] *Package; // pkgs[0] is the current package
npkgs int;
......@@ -134,8 +143,9 @@ func NewScope(parent *Scope) *Scope {
export NewCompilation;
func NewCompilation() *Compilation {
func NewCompilation(flags *Flags) *Compilation {
comp := new(Compilation);
comp.flags = flags;
return comp;
}
......
......@@ -5,19 +5,22 @@
package main
import Build "build"
import Globals "globals"
import Compilation "compilation"
// For now we are not using the flags package to minimize
// external dependencies, and because the requirements are
// very minimal at this point.
func PrintHelp() {
print "go in go (", Build.time, ")\n";
print "usage:\n";
print " go { -v | -vv | file }\n";
/*
printf("flags:\n");
for (int i = 0; Flags[i].name != NULL; i++) {
printf(" %s %s\n", Flags[i].name, Flags[i].help);
}
*/
print " go { flag | file }\n";
print " -d print debug information\n";
print " -s enable semantic checks\n";
print " -v verbose mode\n";
print " -vv very verbose mode\n";
}
......@@ -27,17 +30,22 @@ func main() {
sys.exit(1);
}
verbose := 0;
// collect flags and files
flags := new(Globals.Flags);
files := Globals.NewList();
for i := 1; i < sys.argc(); i++ {
switch sys.argv(i) {
case "-v":
verbose = 1;
continue;
case "-vv":
verbose = 2;
continue;
switch arg := sys.argv(i); arg {
case "-d": flags.debug = true;
case "-s": flags.semantic_checks = true;
case "-v": flags.verbose = 1;
case "-vv": flags.verbose = 2;
default: files.AddStr(arg);
}
Compilation.Compile(sys.argv(i), verbose);
}
// compile files
for p := files.first; p != nil; p = p.next {
comp := Globals.NewCompilation(flags);
Compilation.Compile(comp, p.str);
}
}
......@@ -4,13 +4,13 @@
package Importer
import Utils "utils"
import Globals "globals"
import Object "object"
import Type "type"
import Universe "universe"
export Importer // really only want to export Import()
type Importer struct {
comp *Globals.Compilation;
debug bool;
......@@ -74,7 +74,7 @@ func (I *Importer) ReadString() string {
}
func (I *Importer) ReadObjTag() int {
func (I *Importer) ReadObjectTag() int {
tag := I.ReadInt();
if tag < 0 {
panic "tag < 0";
......@@ -125,14 +125,21 @@ func (I *Importer) ReadScope() *Globals.Scope {
}
scope := Globals.NewScope(nil);
for n := I.ReadInt(); n > 0; n-- {
tag := I.ReadObjTag();
scope.Insert(I.ReadObject(tag));
for {
tag := I.ReadObjectTag();
if tag == 0 {
break;
}
// InsertImport only needed for package scopes
// but ok to use always
scope.InsertImport(I.ReadObject(tag));
}
if I.debug {
print " }";
}
return scope;
}
......@@ -229,13 +236,12 @@ func (I *Importer) ReadType() *Globals.Type {
case Type.FUNCTION:
typ.flags = I.ReadInt();
fallthrough;
case Type.STRUCT: fallthrough;
case Type.INTERFACE:
typ.scope = I.ReadScope();
case Type.POINTER: fallthrough;
case Type.REFERENCE:
case Type.STRUCT, Type.INTERFACE:
typ.scope = I.ReadScope();
case Type.POINTER, Type.REFERENCE:
typ.elt = I.ReadType();
}
......@@ -275,7 +281,7 @@ func (I *Importer) ReadPackage() *Globals.Package {
func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.Package {
I.comp = comp;
I.debug = false;
I.debug = comp.flags.debug;
I.buf = "";
I.pos = 0;
I.npkgs = 0;
......@@ -302,7 +308,7 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
pkg := I.ReadPackage();
for {
tag := I.ReadObjTag();
tag := I.ReadObjectTag();
if tag == 0 {
break;
}
......@@ -317,3 +323,10 @@ func (I *Importer) Import(comp* Globals.Compilation, file_name string) *Globals.
return pkg;
}
export Import
func Import(comp* Globals.Compilation, pkg_name string) *Globals.Package {
var I Importer;
return (&I).Import(comp, Utils.FixExt(pkg_name));
}
......@@ -14,13 +14,10 @@ import Import "import"
import AST "ast"
// So I can submit and have a running parser for now...
const EnableSemanticTests = false;
export Parser
type Parser struct {
comp *Globals.Compilation;
semantic_checks bool;
verbose, indent int;
S *Scanner.Scanner;
......@@ -74,9 +71,10 @@ func (P *Parser) Next() {
}
func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int) {
func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner) {
P.comp = comp;
P.verbose = verbose;
P.semantic_checks = comp.flags.semantic_checks;
P.verbose = comp.flags.verbose;
P.indent = 0;
P.S = S;
P.Next();
......@@ -132,7 +130,7 @@ func (P *Parser) Lookup(ident string) *Globals.Object {
func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
if !EnableSemanticTests {
if !P.semantic_checks {
return;
}
obj.pnolev = P.level;
......@@ -296,7 +294,7 @@ func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
ident = P.ParseIdent();
}
if EnableSemanticTests {
if P.semantic_checks {
obj := P.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared`);
......@@ -355,7 +353,7 @@ func (P *Parser) ParseType() *Globals.Type {
func (P *Parser) ParseTypeName() *Globals.Type {
P.Trace("TypeName");
if EnableSemanticTests {
if P.semantic_checks {
pos := P.pos;
obj := P.ParseQualifiedIdent(-1, "");
typ := obj.typ;
......@@ -496,7 +494,7 @@ func (P *Parser) ParseAnonymousSignature() *Globals.Type {
if P.tok == Scanner.PERIOD {
p0 = sig.entries.len_;
if (EnableSemanticTests && p0 != 1) {
if (P.semantic_checks && p0 != 1) {
P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseAnonymousSignature)";
// TODO do something useful here
......@@ -534,7 +532,7 @@ func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
recv_pos := P.pos;
P.ParseParameters();
p0 = sig.entries.len_;
if (EnableSemanticTests && p0 != 1) {
if (P.semantic_checks && p0 != 1) {
print "p0 = ", p0, "\n";
P.Error(recv_pos, "must have exactly one receiver")
panic "UNIMPLEMENTED (ParseNamedSignature)";
......@@ -653,7 +651,7 @@ func (P *Parser) ParsePointerType() *Globals.Type {
P.Expect(Scanner.MUL);
typ := Globals.NewType(Type.POINTER);
if EnableSemanticTests {
if P.semantic_checks {
if P.tok == Scanner.IDENT {
if P.Lookup(P.val) == nil {
// implicit forward declaration
......@@ -1122,7 +1120,7 @@ func (P *Parser) ParseExpression() {
func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) {
for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
pos, ident := p.val, q.str;
if EnableSemanticTests {
if P.semantic_checks {
obj := P.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared`);
......@@ -1208,24 +1206,24 @@ func (P *Parser) ParseSimpleStat() {
switch P.tok {
case Scanner.COLON:
// label declaration
if EnableSemanticTests && ident_list.len_ != 1 {
if P.semantic_checks && ident_list.len_ != 1 {
P.Error(P.pos, "illegal label declaration");
}
P.Next();
case Scanner.DEFINE:
// variable declaration
if EnableSemanticTests && ident_list.len_ == 0 {
if P.semantic_checks && ident_list.len_ == 0 {
P.Error(P.pos, "illegal left-hand side for declaration");
}
P.Next();
pos := P.pos;
val_list := P.ParseExpressionList();
if EnableSemanticTests && val_list.len_ != ident_list.len_ {
if P.semantic_checks && val_list.len_ != ident_list.len_ {
P.Error(pos, "number of expressions does not match number of variables");
}
// declare variables
if EnableSemanticTests {
if P.semantic_checks {
for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
obj := Globals.NewObject(p.val, Object.VAR, q.str);
P.Declare(obj);
......@@ -1248,13 +1246,13 @@ func (P *Parser) ParseSimpleStat() {
P.Next();
pos := P.pos;
val_list := P.ParseExpressionList();
if EnableSemanticTests && val_list.len_ != expr_list.len_ {
if P.semantic_checks && val_list.len_ != expr_list.len_ {
P.Error(pos, "number of expressions does not match number of variables");
}
default:
P.ConvertToExprList(pos_list, ident_list, expr_list);
if EnableSemanticTests && expr_list.len_ != 1 {
if P.semantic_checks && expr_list.len_ != 1 {
P.Error(P.pos, "no expression list allowed");
}
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
......@@ -1557,11 +1555,10 @@ func (P *Parser) ParseImportSpec() {
obj = P.ParseIdentDecl(Object.PACKAGE);
}
if (EnableSemanticTests && P.tok == Scanner.STRING) {
if (P.semantic_checks && 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)));
pkg := Import.Import(P.comp, pkg_name);
if pkg != nil {
if obj == nil {
// use original package name
......@@ -1776,7 +1773,7 @@ func (P *Parser) ParseDeclaration() {
// Program
func (P *Parser) ResolveUndefTypes() {
if !EnableSemanticTests {
if !P.semantic_checks {
return;
}
......@@ -1798,7 +1795,7 @@ func (P *Parser) ResolveUndefTypes() {
func (P *Parser) MarkExports() {
if !EnableSemanticTests {
if !P.semantic_checks {
return;
}
......@@ -1820,7 +1817,7 @@ func (P *Parser) MarkExports() {
}
} else {
// TODO need to report proper src position
P.Error(0, `"` + p.str + `" is not declared - cannot be exported`);
P.Error(-1, `"` + p.str + `" is not declared - cannot be exported`);
}
}
}
......
......@@ -4,6 +4,9 @@
package Scanner
import Utils "utils"
export
ILLEGAL, EOF, IDENT, STRING, NUMBER,
COMMA, COLON, SEMICOLON, PERIOD,
......@@ -231,6 +234,18 @@ func TokenName(tok int) string {
}
func init() {
Keywords = new(map [string] int);
for i := KEYWORDS_BEG; i <= KEYWORDS_END; i++ {
Keywords[TokenName(i)] = i;
}
// Provide column information in error messages for gri only...
VerboseMsgs = Utils.GetEnv("USER") == "gri";
}
func is_whitespace(ch int) bool {
return ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t';
}
......@@ -370,28 +385,6 @@ bad:
}
func IsUser(username string) bool {
for i := 0; i < sys.envc(); i++ {
if sys.envv(i) == "USER=" + username {
return true;
}
}
return false;
}
func Init() {
Keywords = new(map [string] int);
for i := KEYWORDS_BEG; i <= KEYWORDS_END; i++ {
Keywords[TokenName(i)] = i;
}
// Provide column information in error messages for gri only...
VerboseMsgs = IsUser("gri");
}
// Compute (line, column) information for a given source position.
func (S *Scanner) LineCol(pos int) (line, col int) {
line = 1;
......@@ -416,13 +409,21 @@ func (S *Scanner) LineCol(pos int) (line, col int) {
func (S *Scanner) Error(pos int, msg string) {
const errdist = 10;
delta := pos - S.errpos; // may be negative!
if delta < errdist || delta > errdist || S.nerrors == 0 {
line, col := S.LineCol(pos);
if VerboseMsgs {
print S.filename, ":", line, ":", col, ": ", msg, "\n";
} else {
print S.filename, ":", line, ": ", msg, "\n";
if delta < 0 {
delta = -delta;
}
if delta > errdist || S.nerrors == 0 /* always report first error */ {
print S.filename;
if pos >= 0 {
// print position
line, col := S.LineCol(pos);
if VerboseMsgs {
print ":", line, ":", col;
} else {
print ":", line;
}
}
print ": ", msg, "\n";
S.nerrors++;
S.errpos = pos;
}
......@@ -434,10 +435,6 @@ func (S *Scanner) Error(pos int, msg string) {
func (S *Scanner) Open(filename, src string) {
if Keywords == nil {
Init();
}
S.filename = filename;
S.nerrors = 0;
S.errpos = 0;
......
......@@ -101,8 +101,7 @@ func Register(typ *Globals.Type) *Globals.Type {
}
export Init
func Init() {
func init() {
scope = Globals.NewScope(nil); // universe has no parent
types = Globals.NewList();
......
......@@ -27,3 +27,16 @@ func FixExt(s string) string {
}
return s + ".7";
}
export GetEnv
func GetEnv(key string) string {
n := len(key);
for i := 0; i < sys.envc(); i++ {
v := sys.envv(i);
if v[0 : n] == key {
return v[n + 1 : len(v)]; // +1: skip "="
}
}
return "";
}
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