mirror of
https://github.com/golang/go
synced 2024-11-22 20:24:47 -07:00
- more steps towards tracking idents in scopes
- snapshot of today R=r OCL=22247 CL=22247
This commit is contained in:
parent
289ff7d0e4
commit
cb13c4d552
@ -29,15 +29,15 @@ pretty.6: platform.6 printer.6 compilation.6
|
|||||||
|
|
||||||
compilation.6: platform.6 scanner.6 parser.6 ast.6 typechecker.6
|
compilation.6: platform.6 scanner.6 parser.6 ast.6 typechecker.6
|
||||||
|
|
||||||
ast.6: scanner.6
|
ast.6: scanner.6 globals.6 type.6
|
||||||
|
|
||||||
scanner.6: utils.6
|
scanner.6: utils.6
|
||||||
|
|
||||||
parser.6: scanner.6 ast.6
|
parser.6: scanner.6 ast.6 globals.6 object.6 type.6
|
||||||
|
|
||||||
platform.6: utils.6
|
platform.6: utils.6
|
||||||
|
|
||||||
printer.6: scanner.6 ast.6
|
printer.6: scanner.6 ast.6 globals.6 object.6 type.6
|
||||||
|
|
||||||
typechecker.6: ast.6 universe.6 globals.6 type.6
|
typechecker.6: ast.6 universe.6 globals.6 type.6
|
||||||
|
|
||||||
|
@ -6,12 +6,13 @@ package AST
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"array";
|
"array";
|
||||||
|
Globals "globals";
|
||||||
|
Object "object";
|
||||||
Scanner "scanner";
|
Scanner "scanner";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Object struct;
|
|
||||||
Type struct;
|
Type struct;
|
||||||
Expr struct;
|
Expr struct;
|
||||||
Stat struct;
|
Stat struct;
|
||||||
@ -28,39 +29,16 @@ export type Node struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Objects represent declared language objects, such as a const, type, var;
|
|
||||||
// but also anonymous objects such as type and other literals.
|
|
||||||
|
|
||||||
export type Object struct {
|
|
||||||
Node;
|
|
||||||
lit string; // identifiers and literals
|
|
||||||
typ *Type;
|
|
||||||
val *Expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export func NewObject(pos, tok int, lit string) *Object {
|
|
||||||
obj := new(Object);
|
|
||||||
obj.pos, obj.tok = pos, tok;
|
|
||||||
obj.lit = lit;
|
|
||||||
obj.typ = nil; // Universe::void_typ
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Expressions
|
// Expressions
|
||||||
|
|
||||||
export type Expr struct {
|
export type Expr struct {
|
||||||
Node;
|
Node;
|
||||||
x, y *Expr; // binary (x, y) and unary (y) expressions
|
x, y *Expr; // binary (x, y) and unary (y) expressions
|
||||||
obj *Object;
|
obj *Globals.Object;
|
||||||
|
|
||||||
// TODO find a more space efficient way to hold these
|
// TODO this one should go as well
|
||||||
s string; // identifiers and literals
|
|
||||||
t *Type; // type expressions, function literal types
|
t *Type; // type expressions, function literal types
|
||||||
block *array.Array; end int; // stats for function literals
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -86,9 +64,9 @@ export func NewExpr(pos, tok int, x, y *Expr) *Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export func NewLit(pos, tok int, s string) *Expr {
|
export func NewLit(pos, tok int, obj *Globals.Object) *Expr {
|
||||||
e := new(Expr);
|
e := new(Expr);
|
||||||
e.pos, e.tok, e.s = pos, tok, s;
|
e.pos, e.tok, e.obj = pos, tok, obj;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ func AddDeps(globalset map [string] bool, wset *array.Array, src_file string, fl
|
|||||||
for i := 0; i < nimports; i++ {
|
for i := 0; i < nimports; i++ {
|
||||||
decl := prog.decls.At(i).(*AST.Decl);
|
decl := prog.decls.At(i).(*AST.Decl);
|
||||||
assert(decl.tok == Scanner.IMPORT && decl.val.tok == Scanner.STRING);
|
assert(decl.tok == Scanner.IMPORT && decl.val.tok == Scanner.STRING);
|
||||||
src := decl.val.s;
|
src := decl.val.obj.ident;
|
||||||
src = src[1 : len(src) - 1]; // strip "'s
|
src = src[1 : len(src) - 1]; // strip "'s
|
||||||
|
|
||||||
// ignore files when they are seen a 2nd time
|
// ignore files when they are seen a 2nd time
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package Globals
|
package Globals
|
||||||
|
|
||||||
|
|
||||||
|
import "array"
|
||||||
|
|
||||||
// The following types should really be in their respective files
|
// The following types should really be in their respective files
|
||||||
// (object.go, type.go, scope.go, package.go, compilation.go, etc.) but
|
// (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
|
// they refer to each other and we don't know how to handle forward
|
||||||
@ -29,6 +31,9 @@ export type Object struct {
|
|||||||
ident string;
|
ident string;
|
||||||
typ *Type; // nil for packages
|
typ *Type; // nil for packages
|
||||||
pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
|
pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level
|
||||||
|
|
||||||
|
// attached values
|
||||||
|
block *array.Array; end int; // stats for function literals; end of block pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import Globals "globals"
|
|||||||
|
|
||||||
export const /* kind */ (
|
export const /* kind */ (
|
||||||
BAD = iota; // error handling
|
BAD = iota; // error handling
|
||||||
|
NONE; // kind unknown
|
||||||
CONST; TYPE; VAR; FIELD; FUNC; BUILTIN; PACKAGE; LABEL;
|
CONST; TYPE; VAR; FIELD; FUNC; BUILTIN; PACKAGE; LABEL;
|
||||||
END; // end of scope (import/export only)
|
END; // end of scope (import/export only)
|
||||||
)
|
)
|
||||||
@ -22,6 +23,7 @@ export const /* kind */ (
|
|||||||
export func KindStr(kind int) string {
|
export func KindStr(kind int) string {
|
||||||
switch kind {
|
switch kind {
|
||||||
case BAD: return "BAD";
|
case BAD: return "BAD";
|
||||||
|
case NONE: return "NONE";
|
||||||
case CONST: return "CONST";
|
case CONST: return "CONST";
|
||||||
case TYPE: return "TYPE";
|
case TYPE: return "TYPE";
|
||||||
case VAR: return "VAR";
|
case VAR: return "VAR";
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package Parser
|
package Parser
|
||||||
|
|
||||||
import "array"
|
import "array"
|
||||||
|
import Globals "globals"
|
||||||
|
import Object "object"
|
||||||
import Scanner "scanner"
|
import Scanner "scanner"
|
||||||
import AST "ast"
|
import AST "ast"
|
||||||
|
|
||||||
@ -148,7 +150,8 @@ func ExprType(x *AST.Expr) *AST.Type {
|
|||||||
func (P *Parser) NoType(x *AST.Expr) *AST.Expr {
|
func (P *Parser) NoType(x *AST.Expr) *AST.Expr {
|
||||||
if x != nil && x.tok == Scanner.TYPE {
|
if x != nil && x.tok == Scanner.TYPE {
|
||||||
P.Error(x.pos, "expected expression, found type");
|
P.Error(x.pos, "expected expression, found type");
|
||||||
x = AST.NewLit(x.pos, Scanner.INT, "");
|
val := Globals.NewObject(x.pos, Object.NONE, "0");
|
||||||
|
x = AST.NewLit(x.pos, Scanner.INT, val);
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -173,10 +176,11 @@ func (P *Parser) ParseIdent() *AST.Expr {
|
|||||||
|
|
||||||
x := AST.BadExpr;
|
x := AST.BadExpr;
|
||||||
if P.tok == Scanner.IDENT {
|
if P.tok == Scanner.IDENT {
|
||||||
x = AST.NewLit(P.pos, Scanner.IDENT, P.val);
|
obj := Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||||
|
x = AST.NewLit(P.pos, Scanner.IDENT, obj);
|
||||||
if P.verbose {
|
if P.verbose {
|
||||||
P.PrintIndent();
|
P.PrintIndent();
|
||||||
print("Ident = \"", x.s, "\"\n");
|
print("Ident = \"", x.obj.ident, "\"\n");
|
||||||
}
|
}
|
||||||
P.Next();
|
P.Next();
|
||||||
} else {
|
} else {
|
||||||
@ -658,12 +662,13 @@ func (P *Parser) ParseExpressionList() *AST.Expr {
|
|||||||
func (P *Parser) ParseFunctionLit() *AST.Expr {
|
func (P *Parser) ParseFunctionLit() *AST.Expr {
|
||||||
P.Trace("FunctionLit");
|
P.Trace("FunctionLit");
|
||||||
|
|
||||||
x := AST.NewLit(P.pos, Scanner.FUNC, "");
|
val := Globals.NewObject(P.pos, Object.NONE, "");
|
||||||
|
x := AST.NewLit(P.pos, Scanner.FUNC, val);
|
||||||
P.Expect(Scanner.FUNC);
|
P.Expect(Scanner.FUNC);
|
||||||
x.t = P.ParseFunctionType();
|
x.t = P.ParseFunctionType();
|
||||||
P.expr_lev++;
|
P.expr_lev++;
|
||||||
P.scope_lev++;
|
P.scope_lev++;
|
||||||
x.block, x.end = P.ParseBlock();
|
val.block, val.end = P.ParseBlock();
|
||||||
P.scope_lev--;
|
P.scope_lev--;
|
||||||
P.expr_lev--;
|
P.expr_lev--;
|
||||||
|
|
||||||
@ -712,11 +717,14 @@ func (P *Parser) ParseOperand() *AST.Expr {
|
|||||||
P.Expect(Scanner.RPAREN);
|
P.Expect(Scanner.RPAREN);
|
||||||
|
|
||||||
case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
|
case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
|
||||||
x = AST.NewLit(P.pos, P.tok, P.val);
|
val := Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||||
|
x = AST.NewLit(P.pos, P.tok, val);
|
||||||
P.Next();
|
P.Next();
|
||||||
if x.tok == Scanner.STRING {
|
if x.tok == Scanner.STRING {
|
||||||
|
// TODO should remember the list instead of
|
||||||
|
// concatenate the strings here
|
||||||
for ; P.tok == Scanner.STRING; P.Next() {
|
for ; P.tok == Scanner.STRING; P.Next() {
|
||||||
x.s += P.val;
|
x.obj.ident += P.val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,7 +791,7 @@ func (P *Parser) ParseCall(x0 *AST.Expr) *AST.Expr {
|
|||||||
if P.tok != Scanner.RPAREN {
|
if P.tok != Scanner.RPAREN {
|
||||||
P.expr_lev++;
|
P.expr_lev++;
|
||||||
var t *AST.Type;
|
var t *AST.Type;
|
||||||
if x0.tok == Scanner.IDENT && (x0.s == "new" || x0.s == "make") {
|
if x0.tok == Scanner.IDENT && (x0.obj.ident == "new" || x0.obj.ident == "make") {
|
||||||
// heuristic: assume it's a new(T) or make(T, ...) call, try to parse a type
|
// heuristic: assume it's a new(T) or make(T, ...) call, try to parse a type
|
||||||
t = P.TryType();
|
t = P.TryType();
|
||||||
}
|
}
|
||||||
@ -1367,7 +1375,8 @@ func (P *Parser) ParseImportSpec(pos int) *AST.Decl {
|
|||||||
|
|
||||||
if P.tok == Scanner.STRING {
|
if P.tok == Scanner.STRING {
|
||||||
// TODO eventually the scanner should strip the quotes
|
// TODO eventually the scanner should strip the quotes
|
||||||
d.val = AST.NewLit(P.pos, Scanner.STRING, P.val);
|
val := Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||||
|
d.val = AST.NewLit(P.pos, Scanner.STRING, val);
|
||||||
P.Next();
|
P.Next();
|
||||||
} else {
|
} else {
|
||||||
P.Expect(Scanner.STRING); // use Expect() error handling
|
P.Expect(Scanner.STRING); // use Expect() error handling
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import Flag "flag"
|
import (
|
||||||
import Platform "platform"
|
Flag "flag";
|
||||||
import Printer "printer"
|
Platform "platform";
|
||||||
import Compilation "compilation"
|
Printer "printer";
|
||||||
|
Compilation "compilation";
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -15,7 +17,8 @@ var (
|
|||||||
silent = Flag.Bool("s", false, nil, "silent mode: no pretty print output");
|
silent = Flag.Bool("s", false, nil, "silent mode: no pretty print output");
|
||||||
verbose = Flag.Bool("v", false, &flags.verbose, "verbose mode: trace parsing");
|
verbose = Flag.Bool("v", false, &flags.verbose, "verbose mode: trace parsing");
|
||||||
sixg = Flag.Bool("6g", true, &flags.sixg, "6g compatibility mode");
|
sixg = Flag.Bool("6g", true, &flags.sixg, "6g compatibility mode");
|
||||||
deps = Flag.Bool("d", false, &flags.deps, "print dependency information only");
|
//TODO fix this code again
|
||||||
|
//deps = Flag.Bool("d", false, &flags.deps, "print dependency information only");
|
||||||
columns = Flag.Bool("columns", Platform.USER == "gri", &flags.columns, "print column info in error messages");
|
columns = Flag.Bool("columns", Platform.USER == "gri", &flags.columns, "print column info in error messages");
|
||||||
testmode = Flag.Bool("t", false, &flags.testmode, "test mode: interprets /* ERROR */ and /* SYNC */ comments");
|
testmode = Flag.Bool("t", false, &flags.testmode, "test mode: interprets /* ERROR */ and /* SYNC */ comments");
|
||||||
tokenchan = Flag.Bool("token_chan", false, &flags.tokenchan, "use token channel for scanner-parser connection");
|
tokenchan = Flag.Bool("token_chan", false, &flags.tokenchan, "use token channel for scanner-parser connection");
|
||||||
@ -40,7 +43,7 @@ func main() {
|
|||||||
for i := 0; i < Flag.NArg(); i++ {
|
for i := 0; i < Flag.NArg(); i++ {
|
||||||
src_file := Flag.Arg(i);
|
src_file := Flag.Arg(i);
|
||||||
|
|
||||||
if flags.deps {
|
if false /* DISABLED flags.deps */ {
|
||||||
Compilation.ComputeDeps(src_file, &flags);
|
Compilation.ComputeDeps(src_file, &flags);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -11,6 +11,8 @@ import (
|
|||||||
"tabwriter";
|
"tabwriter";
|
||||||
"flag";
|
"flag";
|
||||||
"fmt";
|
"fmt";
|
||||||
|
Globals "globals";
|
||||||
|
Object "object";
|
||||||
Scanner "scanner";
|
Scanner "scanner";
|
||||||
AST "ast";
|
AST "ast";
|
||||||
)
|
)
|
||||||
@ -363,12 +365,12 @@ func (P *Printer) HtmlEpilogue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Printer) HtmlIdentifier(pos int, ident string) {
|
func (P *Printer) HtmlIdentifier(pos int, obj *Globals.Object) {
|
||||||
if html.BVal() {
|
if html.BVal() {
|
||||||
// no need to HtmlEscape ident
|
// no need to HtmlEscape ident
|
||||||
P.TaggedString(pos, `<a href="#` + ident + `">`, ident, `</a>`);
|
P.TaggedString(pos, `<a href="#` + obj.ident + `">`, obj.ident, `</a>`);
|
||||||
} else {
|
} else {
|
||||||
P.String(pos, ident);
|
P.String(pos, obj.ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,17 +517,17 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) {
|
|||||||
P.Type(x.t);
|
P.Type(x.t);
|
||||||
|
|
||||||
case Scanner.IDENT:
|
case Scanner.IDENT:
|
||||||
P.HtmlIdentifier(x.pos, x.s);
|
P.HtmlIdentifier(x.pos, x.obj);
|
||||||
|
|
||||||
case Scanner.INT, Scanner.STRING, Scanner.FLOAT:
|
case Scanner.INT, Scanner.STRING, Scanner.FLOAT:
|
||||||
// literal
|
// literal
|
||||||
P.String(x.pos, x.s);
|
P.String(x.pos, x.obj.ident);
|
||||||
|
|
||||||
case Scanner.FUNC:
|
case Scanner.FUNC:
|
||||||
// function literal
|
// function literal
|
||||||
P.String(x.pos, "func");
|
P.String(x.pos, "func");
|
||||||
P.Type(x.t);
|
P.Type(x.t);
|
||||||
P.Block(0, x.block, x.end, true);
|
P.Block(0, x.obj.block, x.obj.end, true);
|
||||||
P.newlines = 0;
|
P.newlines = 0;
|
||||||
|
|
||||||
case Scanner.COMMA:
|
case Scanner.COMMA:
|
||||||
|
@ -103,7 +103,7 @@ func (s *State) DeclareIdent(ident *AST.Expr, kind int, typ *AST.Type) {
|
|||||||
// ident is either a comma-separated list or a single ident
|
// ident is either a comma-separated list or a single ident
|
||||||
switch ident.tok {
|
switch ident.tok {
|
||||||
case Scanner.IDENT:
|
case Scanner.IDENT:
|
||||||
obj := Globals.NewObject(ident.pos, kind, ident.s);
|
obj := Globals.NewObject(ident.pos, kind, ident.obj.ident);
|
||||||
s.Declare(obj);
|
s.Declare(obj);
|
||||||
case Scanner.COMMA:
|
case Scanner.COMMA:
|
||||||
s.DeclareIdent(ident.x, kind, typ);
|
s.DeclareIdent(ident.x, kind, typ);
|
||||||
@ -149,7 +149,7 @@ func (s *State) CheckDeclaration(d *AST.Decl) {
|
|||||||
case Scanner.TYPE:
|
case Scanner.TYPE:
|
||||||
assert(d.ident.tok == Scanner.IDENT);
|
assert(d.ident.tok == Scanner.IDENT);
|
||||||
// types may be forward-declared
|
// types may be forward-declared
|
||||||
obj := s.Lookup(d.ident.s);
|
obj := s.Lookup(d.ident.obj.ident);
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
// TODO check if proper forward-declaration
|
// TODO check if proper forward-declaration
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ func (s *State) CheckDeclaration(d *AST.Decl) {
|
|||||||
// TODO
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
// functions may be forward-declared
|
// functions may be forward-declared
|
||||||
obj := s.Lookup(d.ident.s);
|
obj := s.Lookup(d.ident.obj.ident);
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
// TODO check if proper forward-declaration
|
// TODO check if proper forward-declaration
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user