mirror of
https://github.com/golang/go
synced 2024-11-26 04:17:59 -07:00
- preparation to add type info to ast
- consolidation of files, cleanup - more success producing idempotent output for some files with comments containing tabs - snapshot of the day R=r OCL=22474 CL=22474
This commit is contained in:
parent
0c32430534
commit
c620dd9759
@ -29,23 +29,19 @@ pretty.6: platform.6 printer.6 compilation.6
|
||||
|
||||
compilation.6: platform.6 scanner.6 parser.6 ast.6 typechecker.6
|
||||
|
||||
ast.6: scanner.6 globals.6 type.6
|
||||
ast.6: scanner.6
|
||||
|
||||
scanner.6: utils.6
|
||||
|
||||
parser.6: scanner.6 ast.6 globals.6 object.6 type.6
|
||||
parser.6: scanner.6 ast.6
|
||||
|
||||
platform.6: utils.6
|
||||
|
||||
printer.6: scanner.6 ast.6 globals.6 object.6 type.6 utils.6
|
||||
printer.6: scanner.6 ast.6 utils.6
|
||||
|
||||
typechecker.6: ast.6 universe.6 globals.6 type.6
|
||||
typechecker.6: ast.6 universe.6
|
||||
|
||||
universe.6: globals.6 object.6 type.6
|
||||
|
||||
object.6: globals.6
|
||||
|
||||
type.6: globals.6 object.6
|
||||
universe.6: ast.6
|
||||
|
||||
%.6: %.go
|
||||
$(G) $(F) $<
|
||||
|
@ -6,20 +6,154 @@ package AST
|
||||
|
||||
import (
|
||||
"array";
|
||||
Globals "globals";
|
||||
Object "object";
|
||||
Scanner "scanner";
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
Object struct;
|
||||
Type struct;
|
||||
|
||||
Expr struct;
|
||||
Stat struct;
|
||||
Decl struct;
|
||||
)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Objects
|
||||
|
||||
// Object represents a language object, such as a constant, variable, type, etc.
|
||||
|
||||
export const /* kind */ (
|
||||
BADOBJ = iota; // error handling
|
||||
NONE; // kind unknown
|
||||
CONST; TYPE; VAR; FIELD; FUNC; BUILTIN; PACKAGE; LABEL;
|
||||
END; // end of scope (import/export only)
|
||||
)
|
||||
|
||||
|
||||
export func KindStr(kind int) string {
|
||||
switch kind {
|
||||
case BADOBJ: return "BADOBJ";
|
||||
case NONE: return "NONE";
|
||||
case CONST: return "CONST";
|
||||
case TYPE: return "TYPE";
|
||||
case VAR: return "VAR";
|
||||
case FIELD: return "FIELD";
|
||||
case FUNC: return "FUNC";
|
||||
case BUILTIN: return "BUILTIN";
|
||||
case PACKAGE: return "PACKAGE";
|
||||
case LABEL: return "LABEL";
|
||||
case END: return "END";
|
||||
}
|
||||
return "<unknown Object kind>";
|
||||
}
|
||||
|
||||
|
||||
export type Object struct {
|
||||
id int; // unique id
|
||||
|
||||
pos int; // source position (< 0 if unknown position)
|
||||
kind int; // object kind
|
||||
ident string;
|
||||
typ *Type; // nil for packages
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
export var Universe_void_typ *Type // initialized by Universe to Universe.void_typ
|
||||
var ObjectId int;
|
||||
|
||||
export func NewObject(pos, kind int, ident string) *Object {
|
||||
obj := new(Object);
|
||||
obj.id = ObjectId;
|
||||
ObjectId++;
|
||||
|
||||
obj.pos = pos;
|
||||
obj.kind = kind;
|
||||
obj.ident = ident;
|
||||
obj.typ = Universe_void_typ;
|
||||
obj.pnolev = 0;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scopes
|
||||
|
||||
export type Scope struct {
|
||||
parent *Scope;
|
||||
entries map[string] *Object;
|
||||
}
|
||||
|
||||
|
||||
export func NewScope(parent *Scope) *Scope {
|
||||
scope := new(Scope);
|
||||
scope.parent = parent;
|
||||
scope.entries = make(map[string]*Object, 8);
|
||||
return scope;
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) LookupLocal(ident string) *Object {
|
||||
obj, found := scope.entries[ident];
|
||||
if found {
|
||||
return obj;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) Lookup(ident string) *Object {
|
||||
for scope != nil {
|
||||
obj := scope.LookupLocal(ident);
|
||||
if obj != nil {
|
||||
return obj;
|
||||
}
|
||||
scope = scope.parent;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) Add(obj* Object) {
|
||||
scope.entries[obj.ident] = obj;
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) Insert(obj *Object) {
|
||||
if scope.LookupLocal(obj.ident) != nil {
|
||||
panic("obj already inserted");
|
||||
}
|
||||
scope.Add(obj);
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) InsertImport(obj *Object) *Object {
|
||||
p := scope.LookupLocal(obj.ident);
|
||||
if p == nil {
|
||||
scope.Add(obj);
|
||||
p = obj;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
func (scope *Scope) Print() {
|
||||
print("scope {");
|
||||
for key := range scope.entries {
|
||||
print("\n ", key);
|
||||
}
|
||||
print("\n}\n");
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// All nodes have a source position and and token.
|
||||
|
||||
@ -35,7 +169,7 @@ export type Node struct {
|
||||
export type Expr struct {
|
||||
Node;
|
||||
x, y *Expr; // binary (x, y) and unary (y) expressions
|
||||
obj *Globals.Object;
|
||||
obj *Object;
|
||||
|
||||
// TODO this one should go as well
|
||||
t *Type; // type expressions, function literal types
|
||||
@ -64,7 +198,7 @@ export func NewExpr(pos, tok int, x, y *Expr) *Expr {
|
||||
}
|
||||
|
||||
|
||||
export func NewLit(pos, tok int, obj *Globals.Object) *Expr {
|
||||
export func NewLit(pos, tok int, obj *Object) *Expr {
|
||||
e := new(Expr);
|
||||
e.pos, e.tok, e.obj = pos, tok, obj;
|
||||
return e;
|
||||
@ -77,6 +211,74 @@ export var BadExpr = NewExpr(0, Scanner.ILLEGAL, nil, nil);
|
||||
// ----------------------------------------------------------------------------
|
||||
// Types
|
||||
|
||||
export const /* form */ (
|
||||
// internal types
|
||||
// We should never see one of these.
|
||||
UNDEF = iota;
|
||||
|
||||
// VOID types are used when we don't have a type. Never exported.
|
||||
// (exported type forms must be > 0)
|
||||
VOID;
|
||||
|
||||
// BADTYPE types are compatible with any type and don't cause further errors.
|
||||
// They are introduced only as a result of an error in the source code. A
|
||||
// correct program cannot have BAD types.
|
||||
BADTYPE;
|
||||
|
||||
// FORWARD types are forward-declared (incomplete) types. They can only
|
||||
// be used as element types of pointer types and must be resolved before
|
||||
// their internals are accessible.
|
||||
FORWARD;
|
||||
|
||||
// TUPLE types represent multi-valued result types of functions and
|
||||
// methods.
|
||||
TUPLE;
|
||||
|
||||
// The type of nil.
|
||||
NIL;
|
||||
|
||||
// A type name
|
||||
TYPENAME;
|
||||
|
||||
// basic types
|
||||
BOOL; UINT; INT; FLOAT; STRING; INTEGER;
|
||||
|
||||
// composite types
|
||||
ALIAS; ARRAY; STRUCT; INTERFACE; MAP; CHANNEL; FUNCTION; METHOD; POINTER;
|
||||
|
||||
// open-ended parameter type
|
||||
ELLIPSIS
|
||||
)
|
||||
|
||||
|
||||
export func FormStr(form int) string {
|
||||
switch form {
|
||||
case VOID: return "VOID";
|
||||
case BADTYPE: return "BADTYPE";
|
||||
case FORWARD: return "FORWARD";
|
||||
case TUPLE: return "TUPLE";
|
||||
case NIL: return "NIL";
|
||||
case TYPENAME: return "TYPENAME";
|
||||
case BOOL: return "BOOL";
|
||||
case UINT: return "UINT";
|
||||
case INT: return "INT";
|
||||
case FLOAT: return "FLOAT";
|
||||
case STRING: return "STRING";
|
||||
case ALIAS: return "ALIAS";
|
||||
case ARRAY: return "ARRAY";
|
||||
case STRUCT: return "STRUCT";
|
||||
case INTERFACE: return "INTERFACE";
|
||||
case MAP: return "MAP";
|
||||
case CHANNEL: return "CHANNEL";
|
||||
case FUNCTION: return "FUNCTION";
|
||||
case METHOD: return "METHOD";
|
||||
case POINTER: return "POINTER";
|
||||
case ELLIPSIS: return "ELLIPSIS";
|
||||
}
|
||||
return "<unknown Type form>";
|
||||
}
|
||||
|
||||
|
||||
export const /* channel mode */ (
|
||||
FULL = iota;
|
||||
SEND;
|
||||
@ -85,15 +287,39 @@ export const /* channel mode */ (
|
||||
|
||||
|
||||
export type Type struct {
|
||||
Node;
|
||||
id int; // unique id
|
||||
|
||||
ref int; // for exporting only: >= 0 means already exported
|
||||
form int; // type form
|
||||
size int; // size in bytes
|
||||
obj *Object; // primary type object or NULL
|
||||
scope *Scope; // forwards, structs, interfaces, functions
|
||||
|
||||
// syntactic components
|
||||
pos int; // source position (< 0 if unknown position)
|
||||
expr *Expr; // type name, array length
|
||||
mode int; // channel mode
|
||||
key *Type; // receiver type, map key
|
||||
elt *Type; // array element, map or channel value, or pointer base type, result type
|
||||
key *Type; // receiver type or map key
|
||||
elt *Type; // array, map, channel or pointer element type, function result type
|
||||
list *array.Array; end int; // struct fields, interface methods, function parameters
|
||||
}
|
||||
|
||||
|
||||
var TypeId int;
|
||||
|
||||
export func NewType(pos, form int) *Type {
|
||||
typ := new(Type);
|
||||
typ.id = TypeId;
|
||||
TypeId++;
|
||||
|
||||
typ.ref = -1; // not yet exported
|
||||
typ.pos = pos;
|
||||
typ.form = form;
|
||||
|
||||
return typ;
|
||||
}
|
||||
|
||||
|
||||
func (t *Type) nfields() int {
|
||||
if t.list == nil {
|
||||
return 0;
|
||||
@ -113,14 +339,7 @@ func (t *Type) nfields() int {
|
||||
}
|
||||
|
||||
|
||||
export func NewType(pos, tok int) *Type {
|
||||
t := new(Type);
|
||||
t.pos, t.tok = pos, tok;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
// requires complete Type type
|
||||
// requires complete Type.pos access
|
||||
export func NewTypeExpr(t *Type) *Expr {
|
||||
e := new(Expr);
|
||||
e.pos, e.tok, e.t = t.pos, Scanner.TYPE, t;
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
package Parser
|
||||
|
||||
import "array"
|
||||
import Globals "globals"
|
||||
import Object "object"
|
||||
import Scanner "scanner"
|
||||
import AST "ast"
|
||||
import (
|
||||
"array";
|
||||
Scanner "scanner";
|
||||
AST "ast";
|
||||
)
|
||||
|
||||
|
||||
export type Parser struct {
|
||||
@ -34,7 +34,7 @@ export type Parser struct {
|
||||
scope_lev int; // 0 = global scope, 1 = function scope of global functions, etc.
|
||||
|
||||
// Scopes
|
||||
top_scope *Globals.Scope;
|
||||
top_scope *AST.Scope;
|
||||
};
|
||||
|
||||
|
||||
@ -154,7 +154,7 @@ func (P *Parser) OptSemicolon() {
|
||||
// Scopes
|
||||
|
||||
func (P *Parser) OpenScope() {
|
||||
P.top_scope = Globals.NewScope(P.top_scope);
|
||||
P.top_scope = AST.NewScope(P.top_scope);
|
||||
}
|
||||
|
||||
|
||||
@ -163,27 +163,15 @@ func (P *Parser) CloseScope() {
|
||||
}
|
||||
|
||||
|
||||
func Lookup(scope *Globals.Scope, ident string) *Globals.Object {
|
||||
for scope != nil {
|
||||
obj := scope.Lookup(ident);
|
||||
if obj != nil {
|
||||
return obj;
|
||||
}
|
||||
scope = scope.parent;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) DeclareInScope(scope *Globals.Scope, x *AST.Expr, kind int) {
|
||||
func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) {
|
||||
if P.scope_lev < 0 {
|
||||
panic("cannot declare objects in other packages");
|
||||
}
|
||||
obj := x.obj;
|
||||
assert(x.tok == Scanner.IDENT && obj.kind == Object.NONE);
|
||||
assert(x.tok == Scanner.IDENT && obj.kind == AST.NONE);
|
||||
obj.kind = kind;
|
||||
obj.pnolev = P.scope_lev;
|
||||
if scope.Lookup(obj.ident) != nil {
|
||||
if scope.LookupLocal(obj.ident) != nil {
|
||||
P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
|
||||
return; // don't insert it into the scope
|
||||
}
|
||||
@ -210,11 +198,11 @@ func ExprType(x *AST.Expr) *AST.Type {
|
||||
t = x.t;
|
||||
} else if x.tok == Scanner.IDENT {
|
||||
// assume a type name
|
||||
t = AST.NewType(x.pos, Scanner.IDENT);
|
||||
t = AST.NewType(x.pos, AST.TYPENAME);
|
||||
t.expr = x;
|
||||
} else if x.tok == Scanner.PERIOD && x.y != nil && ExprType(x.x) != nil {
|
||||
// possibly a qualified (type) identifier
|
||||
t = AST.NewType(x.pos, Scanner.IDENT);
|
||||
t = AST.NewType(x.pos, AST.TYPENAME);
|
||||
t.expr = x;
|
||||
}
|
||||
return t;
|
||||
@ -224,7 +212,7 @@ func ExprType(x *AST.Expr) *AST.Type {
|
||||
func (P *Parser) NoType(x *AST.Expr) *AST.Expr {
|
||||
if x != nil && x.tok == Scanner.TYPE {
|
||||
P.Error(x.pos, "expected expression, found type");
|
||||
val := Globals.NewObject(x.pos, Object.NONE, "0");
|
||||
val := AST.NewObject(x.pos, AST.NONE, "0");
|
||||
x = AST.NewLit(x.pos, Scanner.INT, val);
|
||||
}
|
||||
return x;
|
||||
@ -246,19 +234,19 @@ func (P *Parser) ParseDeclaration() *AST.Decl;
|
||||
|
||||
|
||||
// If scope != nil, lookup identifier in scope. Otherwise create one.
|
||||
func (P *Parser) ParseIdent(scope *Globals.Scope) *AST.Expr {
|
||||
func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr {
|
||||
P.Trace("Ident");
|
||||
|
||||
x := AST.BadExpr;
|
||||
if P.tok == Scanner.IDENT {
|
||||
var obj *Globals.Object;
|
||||
var obj *AST.Object;
|
||||
if scope != nil {
|
||||
obj = Lookup(scope, P.val);
|
||||
obj = scope.Lookup(P.val);
|
||||
}
|
||||
if obj == nil {
|
||||
obj = Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||
obj = AST.NewObject(P.pos, AST.NONE, P.val);
|
||||
} else {
|
||||
assert(obj.kind != Object.NONE);
|
||||
assert(obj.kind != AST.NONE);
|
||||
}
|
||||
x = AST.NewLit(P.pos, Scanner.IDENT, obj);
|
||||
if P.verbose {
|
||||
@ -344,7 +332,7 @@ func (P *Parser) ParseQualifiedIdent() *AST.Expr {
|
||||
func (P *Parser) ParseTypeName() *AST.Type {
|
||||
P.Trace("TypeName");
|
||||
|
||||
t := AST.NewType(P.pos, P.tok);
|
||||
t := AST.NewType(P.pos, AST.TYPENAME);
|
||||
t.expr = P.ParseQualifiedIdent();
|
||||
|
||||
P.Ecart();
|
||||
@ -355,7 +343,7 @@ func (P *Parser) ParseTypeName() *AST.Type {
|
||||
func (P *Parser) ParseArrayType() *AST.Type {
|
||||
P.Trace("ArrayType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.LBRACK);
|
||||
t := AST.NewType(P.pos, AST.ARRAY);
|
||||
P.Expect(Scanner.LBRACK);
|
||||
if P.tok == Scanner.ELLIPSIS {
|
||||
t.expr = P.NewExpr(P.pos, Scanner.ELLIPSIS, nil, nil);
|
||||
@ -374,7 +362,7 @@ func (P *Parser) ParseArrayType() *AST.Type {
|
||||
func (P *Parser) ParseChannelType() *AST.Type {
|
||||
P.Trace("ChannelType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.CHAN);
|
||||
t := AST.NewType(P.pos, AST.CHANNEL);
|
||||
t.mode = AST.FULL;
|
||||
if P.tok == Scanner.CHAN {
|
||||
P.Next();
|
||||
@ -401,10 +389,10 @@ func (P *Parser) ParseVarDecl(expect_ident bool) *AST.Type {
|
||||
t := AST.BadType;
|
||||
if expect_ident {
|
||||
x := P.ParseIdent(nil);
|
||||
t = AST.NewType(x.pos, Scanner.IDENT);
|
||||
t = AST.NewType(x.pos, AST.TYPENAME);
|
||||
t.expr = x;
|
||||
} else if P.tok == Scanner.ELLIPSIS {
|
||||
t = AST.NewType(P.pos, Scanner.ELLIPSIS);
|
||||
t = AST.NewType(P.pos, AST.ELLIPSIS);
|
||||
P.Next();
|
||||
} else {
|
||||
t = P.ParseType();
|
||||
@ -429,7 +417,7 @@ func (P *Parser) ParseVarDeclList(list *array.Array, ellipsis_ok bool) {
|
||||
|
||||
typ := P.TryType();
|
||||
if typ == nil && P.tok == Scanner.ELLIPSIS {
|
||||
typ = AST.NewType(P.pos, Scanner.ELLIPSIS);
|
||||
typ = AST.NewType(P.pos, AST.ELLIPSIS);
|
||||
P.Next();
|
||||
}
|
||||
|
||||
@ -445,7 +433,7 @@ func (P *Parser) ParseVarDeclList(list *array.Array, ellipsis_ok bool) {
|
||||
// convert the type entries into identifiers
|
||||
for i, n := i0, list.Len(); i < n; i++ {
|
||||
t := list.At(i).(*AST.Type);
|
||||
if t.tok == Scanner.IDENT && t.expr.tok == Scanner.IDENT {
|
||||
if t.form == AST.TYPENAME && t.expr.tok == Scanner.IDENT {
|
||||
list.Set(i, t.expr);
|
||||
} else {
|
||||
list.Set(i, AST.BadExpr);
|
||||
@ -486,7 +474,7 @@ func (P *Parser) ParseParameterList(ellipsis_ok bool) *array.Array {
|
||||
func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type {
|
||||
P.Trace("Parameters");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.STRUCT);
|
||||
t := AST.NewType(P.pos, AST.STRUCT);
|
||||
P.Expect(Scanner.LPAREN);
|
||||
if P.tok != Scanner.RPAREN {
|
||||
t.list = P.ParseParameterList(ellipsis_ok);
|
||||
@ -524,7 +512,7 @@ func (P *Parser) ParseResult() *AST.Type {
|
||||
} else {
|
||||
typ := P.TryType();
|
||||
if typ != nil {
|
||||
t = AST.NewType(P.pos, Scanner.STRUCT);
|
||||
t = AST.NewType(P.pos, AST.STRUCT);
|
||||
t.list = array.New(0);
|
||||
t.list.Push(AST.NewTypeExpr(typ));
|
||||
t.end = P.pos;
|
||||
@ -548,7 +536,7 @@ func (P *Parser) ParseFunctionType() *AST.Type {
|
||||
P.OpenScope();
|
||||
P.scope_lev++;
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.LPAREN);
|
||||
t := AST.NewType(P.pos, AST.FUNCTION);
|
||||
t.list = P.ParseParameters(true).list; // TODO find better solution
|
||||
t.end = P.pos;
|
||||
t.elt = P.ParseResult();
|
||||
@ -580,7 +568,7 @@ func (P *Parser) ParseMethodSpec(list *array.Array) {
|
||||
func (P *Parser) ParseInterfaceType() *AST.Type {
|
||||
P.Trace("InterfaceType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.INTERFACE);
|
||||
t := AST.NewType(P.pos, AST.INTERFACE);
|
||||
P.Expect(Scanner.INTERFACE);
|
||||
if P.tok == Scanner.LBRACE {
|
||||
P.Next();
|
||||
@ -609,7 +597,7 @@ func (P *Parser) ParseInterfaceType() *AST.Type {
|
||||
func (P *Parser) ParseMapType() *AST.Type {
|
||||
P.Trace("MapType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.MAP);
|
||||
t := AST.NewType(P.pos, AST.MAP);
|
||||
P.Expect(Scanner.MAP);
|
||||
P.Expect(Scanner.LBRACK);
|
||||
t.key = P.ParseVarType();
|
||||
@ -626,7 +614,7 @@ func (P *Parser) ParseOperand() *AST.Expr
|
||||
func (P *Parser) ParseStructType() *AST.Type {
|
||||
P.Trace("StructType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.STRUCT);
|
||||
t := AST.NewType(P.pos, AST.STRUCT);
|
||||
P.Expect(Scanner.STRUCT);
|
||||
if P.tok == Scanner.LBRACE {
|
||||
P.Next();
|
||||
@ -662,7 +650,7 @@ func (P *Parser) ParseStructType() *AST.Type {
|
||||
func (P *Parser) ParsePointerType() *AST.Type {
|
||||
P.Trace("PointerType");
|
||||
|
||||
t := AST.NewType(P.pos, Scanner.MUL);
|
||||
t := AST.NewType(P.pos, AST.POINTER);
|
||||
P.Expect(Scanner.MUL);
|
||||
t.elt = P.ParseType();
|
||||
|
||||
@ -769,7 +757,7 @@ func (P *Parser) ParseExpressionList() *AST.Expr {
|
||||
func (P *Parser) ParseFunctionLit() *AST.Expr {
|
||||
P.Trace("FunctionLit");
|
||||
|
||||
val := Globals.NewObject(P.pos, Object.NONE, "");
|
||||
val := AST.NewObject(P.pos, AST.NONE, "");
|
||||
x := AST.NewLit(P.pos, Scanner.FUNC, val);
|
||||
P.Expect(Scanner.FUNC);
|
||||
x.t = P.ParseFunctionType();
|
||||
@ -824,7 +812,7 @@ func (P *Parser) ParseOperand() *AST.Expr {
|
||||
P.Expect(Scanner.RPAREN);
|
||||
|
||||
case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
|
||||
val := Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||
val := AST.NewObject(P.pos, AST.NONE, P.val);
|
||||
x = AST.NewLit(P.pos, P.tok, val);
|
||||
P.Next();
|
||||
if x.tok == Scanner.STRING {
|
||||
@ -1033,7 +1021,7 @@ func (P *Parser) ParseUnaryExpr() *AST.Expr {
|
||||
y := P.ParseUnaryExpr();
|
||||
if tok == Scanner.MUL && y.tok == Scanner.TYPE {
|
||||
// pointer type
|
||||
t := AST.NewType(pos, Scanner.MUL);
|
||||
t := AST.NewType(pos, AST.POINTER);
|
||||
t.elt = y.t;
|
||||
x = AST.NewTypeExpr(t);
|
||||
} else {
|
||||
@ -1491,7 +1479,7 @@ func (P *Parser) ParseImportSpec(pos int) *AST.Decl {
|
||||
|
||||
if P.tok == Scanner.STRING {
|
||||
// TODO eventually the scanner should strip the quotes
|
||||
val := Globals.NewObject(P.pos, Object.NONE, P.val);
|
||||
val := AST.NewObject(P.pos, AST.NONE, P.val);
|
||||
d.val = AST.NewLit(P.pos, Scanner.STRING, val);
|
||||
P.Next();
|
||||
} else {
|
||||
@ -1499,7 +1487,7 @@ func (P *Parser) ParseImportSpec(pos int) *AST.Decl {
|
||||
}
|
||||
|
||||
if d.ident != nil {
|
||||
P.Declare(d.ident, Object.PACKAGE);
|
||||
P.Declare(d.ident, AST.PACKAGE);
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
@ -1518,7 +1506,7 @@ func (P *Parser) ParseConstSpec(exported bool, pos int) *AST.Decl {
|
||||
d.val = P.ParseExpressionList();
|
||||
}
|
||||
|
||||
P.Declare(d.ident, Object.CONST);
|
||||
P.Declare(d.ident, AST.CONST);
|
||||
|
||||
P.Ecart();
|
||||
return d;
|
||||
@ -1554,7 +1542,7 @@ func (P *Parser) ParseVarSpec(exported bool, pos int) *AST.Decl {
|
||||
}
|
||||
}
|
||||
|
||||
P.Declare(d.ident, Object.VAR);
|
||||
P.Declare(d.ident, AST.VAR);
|
||||
|
||||
P.Ecart();
|
||||
return d;
|
||||
|
@ -12,8 +12,6 @@ import (
|
||||
"flag";
|
||||
"fmt";
|
||||
Utils "utils";
|
||||
Globals "globals";
|
||||
Object "object";
|
||||
Scanner "scanner";
|
||||
AST "ast";
|
||||
)
|
||||
@ -127,6 +125,23 @@ func HtmlEscape(s string) string {
|
||||
}
|
||||
|
||||
|
||||
// Reduce contiguous sequences of '\t' in a string to a single '\t'.
|
||||
func Untabify(s string) string {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '\t' {
|
||||
j := i;
|
||||
for j < len(s) && s[j] == '\t' {
|
||||
j++;
|
||||
}
|
||||
if j-i > 1 { // more then one tab
|
||||
return s[0 : i+1] + Untabify(s[j : len(s)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) Printf(format string, s ...) {
|
||||
n, err := fmt.fprintf(P.text, format, s);
|
||||
if err != nil {
|
||||
@ -246,7 +261,9 @@ func (P *Printer) TaggedString(pos int, tag, s, endtag string) {
|
||||
if *debug {
|
||||
P.Printf("[%d]", P.cpos);
|
||||
}
|
||||
P.Printf("%s", HtmlEscape(ctext));
|
||||
// calling Untabify increases the change for idempotent output
|
||||
// since tabs in comments are also interpreted by tabwriter
|
||||
P.Printf("%s", HtmlEscape(Untabify(ctext)));
|
||||
|
||||
if ctext[1] == '/' {
|
||||
//-style comments must end in newline
|
||||
@ -371,7 +388,7 @@ func (P *Printer) HtmlIdentifier(x *AST.Expr) {
|
||||
panic();
|
||||
}
|
||||
obj := x.obj;
|
||||
if *html && obj.kind != Object.NONE {
|
||||
if *html && obj.kind != AST.NONE {
|
||||
// depending on whether we have a declaration or use, generate different html
|
||||
// - no need to HtmlEscape ident
|
||||
id := Utils.IntToString(obj.id, 10);
|
||||
@ -450,11 +467,11 @@ func (P *Printer) Fields(list *array.Array, end int) {
|
||||
func (P *Printer) Type(t *AST.Type) int {
|
||||
separator := semicolon;
|
||||
|
||||
switch t.tok {
|
||||
case Scanner.IDENT:
|
||||
switch t.form {
|
||||
case AST.TYPENAME:
|
||||
P.Expr(t.expr);
|
||||
|
||||
case Scanner.LBRACK:
|
||||
case AST.ARRAY:
|
||||
P.String(t.pos, "[");
|
||||
if t.expr != nil {
|
||||
P.Expr(t.expr);
|
||||
@ -462,21 +479,24 @@ func (P *Printer) Type(t *AST.Type) int {
|
||||
P.String(0, "]");
|
||||
separator = P.Type(t.elt);
|
||||
|
||||
case Scanner.STRUCT, Scanner.INTERFACE:
|
||||
P.Token(t.pos, t.tok);
|
||||
case AST.STRUCT, AST.INTERFACE:
|
||||
switch t.form {
|
||||
case AST.STRUCT: P.String(t.pos, "struct");
|
||||
case AST.INTERFACE: P.String(t.pos, "interface");
|
||||
}
|
||||
if t.list != nil {
|
||||
P.separator = blank;
|
||||
P.Fields(t.list, t.end);
|
||||
}
|
||||
separator = none;
|
||||
|
||||
case Scanner.MAP:
|
||||
case AST.MAP:
|
||||
P.String(t.pos, "map [");
|
||||
P.Type(t.key);
|
||||
P.String(0, "]");
|
||||
separator = P.Type(t.elt);
|
||||
|
||||
case Scanner.CHAN:
|
||||
case AST.CHANNEL:
|
||||
var m string;
|
||||
switch t.mode {
|
||||
case AST.FULL: m = "chan ";
|
||||
@ -486,11 +506,11 @@ func (P *Printer) Type(t *AST.Type) int {
|
||||
P.String(t.pos, m);
|
||||
separator = P.Type(t.elt);
|
||||
|
||||
case Scanner.MUL:
|
||||
case AST.POINTER:
|
||||
P.String(t.pos, "*");
|
||||
separator = P.Type(t.elt);
|
||||
|
||||
case Scanner.LPAREN:
|
||||
case AST.FUNCTION:
|
||||
P.Parameters(t.pos, t.list);
|
||||
if t.elt != nil {
|
||||
P.separator = blank;
|
||||
@ -503,11 +523,11 @@ func (P *Printer) Type(t *AST.Type) int {
|
||||
}
|
||||
}
|
||||
|
||||
case Scanner.ELLIPSIS:
|
||||
case AST.ELLIPSIS:
|
||||
P.String(t.pos, "...");
|
||||
|
||||
default:
|
||||
P.Error(t.pos, t.tok, "type");
|
||||
P.Error(t.pos, t.form, "type");
|
||||
}
|
||||
|
||||
return separator;
|
||||
|
@ -679,7 +679,8 @@ func (S *Scanner) Select4(tok0, tok1, ch2, tok2, tok3 int) int {
|
||||
|
||||
|
||||
func (S *Scanner) Scan() (pos, tok int, val string) {
|
||||
L: S.SkipWhitespace();
|
||||
loop:
|
||||
S.SkipWhitespace();
|
||||
|
||||
pos, tok = S.chpos, ILLEGAL;
|
||||
|
||||
@ -722,7 +723,7 @@ L: S.SkipWhitespace();
|
||||
if S.ch == '/' || S.ch == '*' {
|
||||
tok, val = COMMENT, S.ScanComment();
|
||||
if !S.scan_comments {
|
||||
goto L;
|
||||
goto loop;
|
||||
}
|
||||
} else {
|
||||
tok = S.Select2(QUO, QUO_ASSIGN);
|
||||
|
@ -22,11 +22,9 @@ count() {
|
||||
apply1() {
|
||||
#echo $1 $2
|
||||
case `basename $F` in
|
||||
# these files don't pass the idempotency test yet
|
||||
log.go | type.go | types_amd64_darwin.go | \
|
||||
\
|
||||
# files with errors (skip them)
|
||||
method1.go | selftest1.go | func3.go | bug014.go | bug029.go | bug032.go | bug050.go | \
|
||||
bug068.go | bug088.go | bug083.go | bug106.go | bug125.go | bug126.go ) ;; # skip - files contain errors
|
||||
bug068.go | bug088.go | bug083.go | bug106.go | bug125.go | bug126.go ) ;;
|
||||
* ) $1 $2; count ;;
|
||||
esac
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ import (
|
||||
AST "ast";
|
||||
Scanner "scanner";
|
||||
Universe "universe";
|
||||
Globals "globals";
|
||||
Object "object";
|
||||
Type "type";
|
||||
)
|
||||
|
||||
|
||||
|
@ -6,14 +6,12 @@ package Universe
|
||||
|
||||
import (
|
||||
"array";
|
||||
Globals "globals";
|
||||
Object "object";
|
||||
Type "type";
|
||||
AST "ast";
|
||||
)
|
||||
|
||||
|
||||
export var (
|
||||
scope *Globals.Scope;
|
||||
scope *AST.Scope;
|
||||
types array.Array;
|
||||
|
||||
// internal types
|
||||
@ -42,19 +40,19 @@ export var (
|
||||
uint_typ,
|
||||
int_typ,
|
||||
float_typ,
|
||||
uintptr_typ *Globals.Type;
|
||||
uintptr_typ *AST.Type;
|
||||
|
||||
true_obj,
|
||||
false_obj,
|
||||
iota_obj,
|
||||
nil_obj *Globals.Object;
|
||||
nil_obj *AST.Object;
|
||||
)
|
||||
|
||||
|
||||
func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object {
|
||||
obj := Globals.NewObject(-1 /* no source pos */, kind, ident);
|
||||
func DeclObj(kind int, ident string, typ *AST.Type) *AST.Object {
|
||||
obj := AST.NewObject(-1 /* no source pos */, kind, ident);
|
||||
obj.typ = typ;
|
||||
if kind == Object.TYPE && typ.obj == nil {
|
||||
if kind == AST.TYPE && typ.obj == nil {
|
||||
typ.obj = obj; // set primary type object
|
||||
}
|
||||
scope.Insert(obj);
|
||||
@ -62,14 +60,14 @@ func DeclObj(kind int, ident string, typ *Globals.Type) *Globals.Object {
|
||||
}
|
||||
|
||||
|
||||
func DeclType(form int, ident string, size int) *Globals.Type {
|
||||
typ := Globals.NewType(form);
|
||||
func DeclType(form int, ident string, size int) *AST.Type {
|
||||
typ := AST.NewType(-1 /* no source pos */, form);
|
||||
typ.size = size;
|
||||
return DeclObj(Object.TYPE, ident, typ).typ;
|
||||
return DeclObj(AST.TYPE, ident, typ).typ;
|
||||
}
|
||||
|
||||
|
||||
func Register(typ *Globals.Type) *Globals.Type {
|
||||
func Register(typ *AST.Type) *AST.Type {
|
||||
typ.ref = types.Len();
|
||||
types.Push(typ);
|
||||
return typ;
|
||||
@ -77,49 +75,49 @@ func Register(typ *Globals.Type) *Globals.Type {
|
||||
|
||||
|
||||
func init() {
|
||||
scope = Globals.NewScope(nil); // universe has no parent
|
||||
scope = AST.NewScope(nil); // universe has no parent
|
||||
types.Init(32);
|
||||
|
||||
// Interal types
|
||||
void_typ = Globals.NewType(Type.VOID);
|
||||
Globals.Universe_void_typ = void_typ;
|
||||
bad_typ = Globals.NewType(Type.BAD);
|
||||
nil_typ = Globals.NewType(Type.NIL);
|
||||
void_typ = AST.NewType(-1 /* no source pos */, AST.VOID);
|
||||
AST.Universe_void_typ = void_typ;
|
||||
bad_typ = AST.NewType(-1 /* no source pos */, AST.BADTYPE);
|
||||
nil_typ = AST.NewType(-1 /* no source pos */, AST.NIL);
|
||||
|
||||
// Basic types
|
||||
bool_typ = Register(DeclType(Type.BOOL, "bool", 1));
|
||||
uint8_typ = Register(DeclType(Type.UINT, "uint8", 1));
|
||||
uint16_typ = Register(DeclType(Type.UINT, "uint16", 2));
|
||||
uint32_typ = Register(DeclType(Type.UINT, "uint32", 4));
|
||||
uint64_typ = Register(DeclType(Type.UINT, "uint64", 8));
|
||||
int8_typ = Register(DeclType(Type.INT, "int8", 1));
|
||||
int16_typ = Register(DeclType(Type.INT, "int16", 2));
|
||||
int32_typ = Register(DeclType(Type.INT, "int32", 4));
|
||||
int64_typ = Register(DeclType(Type.INT, "int64", 8));
|
||||
float32_typ = Register(DeclType(Type.FLOAT, "float32", 4));
|
||||
float64_typ = Register(DeclType(Type.FLOAT, "float64", 8));
|
||||
float80_typ = Register(DeclType(Type.FLOAT, "float80", 10));
|
||||
string_typ = Register(DeclType(Type.STRING, "string", 8));
|
||||
integer_typ = Register(DeclType(Type.INTEGER, "integer", 8));
|
||||
bool_typ = Register(DeclType(AST.BOOL, "bool", 1));
|
||||
uint8_typ = Register(DeclType(AST.UINT, "uint8", 1));
|
||||
uint16_typ = Register(DeclType(AST.UINT, "uint16", 2));
|
||||
uint32_typ = Register(DeclType(AST.UINT, "uint32", 4));
|
||||
uint64_typ = Register(DeclType(AST.UINT, "uint64", 8));
|
||||
int8_typ = Register(DeclType(AST.INT, "int8", 1));
|
||||
int16_typ = Register(DeclType(AST.INT, "int16", 2));
|
||||
int32_typ = Register(DeclType(AST.INT, "int32", 4));
|
||||
int64_typ = Register(DeclType(AST.INT, "int64", 8));
|
||||
float32_typ = Register(DeclType(AST.FLOAT, "float32", 4));
|
||||
float64_typ = Register(DeclType(AST.FLOAT, "float64", 8));
|
||||
float80_typ = Register(DeclType(AST.FLOAT, "float80", 10));
|
||||
string_typ = Register(DeclType(AST.STRING, "string", 8));
|
||||
integer_typ = Register(DeclType(AST.INTEGER, "integer", 8));
|
||||
|
||||
// All but 'byte' should be platform-dependent, eventually.
|
||||
byte_typ = Register(DeclType(Type.UINT, "byte", 1));
|
||||
uint_typ = Register(DeclType(Type.UINT, "uint", 4));
|
||||
int_typ = Register(DeclType(Type.INT, "int", 4));
|
||||
float_typ = Register(DeclType(Type.FLOAT, "float", 4));
|
||||
uintptr_typ = Register(DeclType(Type.UINT, "uintptr", 8));
|
||||
byte_typ = Register(DeclType(AST.UINT, "byte", 1));
|
||||
uint_typ = Register(DeclType(AST.UINT, "uint", 4));
|
||||
int_typ = Register(DeclType(AST.INT, "int", 4));
|
||||
float_typ = Register(DeclType(AST.FLOAT, "float", 4));
|
||||
uintptr_typ = Register(DeclType(AST.UINT, "uintptr", 8));
|
||||
|
||||
// Predeclared constants
|
||||
true_obj = DeclObj(Object.CONST, "true", bool_typ);
|
||||
false_obj = DeclObj(Object.CONST, "false", bool_typ);
|
||||
iota_obj = DeclObj(Object.CONST, "iota", int_typ);
|
||||
nil_obj = DeclObj(Object.CONST, "nil", nil_typ);
|
||||
true_obj = DeclObj(AST.CONST, "true", bool_typ);
|
||||
false_obj = DeclObj(AST.CONST, "false", bool_typ);
|
||||
iota_obj = DeclObj(AST.CONST, "iota", int_typ);
|
||||
nil_obj = DeclObj(AST.CONST, "nil", nil_typ);
|
||||
|
||||
// Builtin functions
|
||||
DeclObj(Object.BUILTIN, "len", void_typ);
|
||||
DeclObj(Object.BUILTIN, "new", void_typ);
|
||||
DeclObj(Object.BUILTIN, "panic", void_typ);
|
||||
DeclObj(Object.BUILTIN, "print", void_typ);
|
||||
DeclObj(AST.BUILTIN, "len", void_typ);
|
||||
DeclObj(AST.BUILTIN, "new", void_typ);
|
||||
DeclObj(AST.BUILTIN, "panic", void_typ);
|
||||
DeclObj(AST.BUILTIN, "print", void_typ);
|
||||
|
||||
// scope.Print();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user