Node;
x, y *Expr; // binary (x, y) and unary (y) expressions
obj *Object;
-
- // TODO this one should go as well
- t *Type; // type expressions, function literal types
}
}
-export func NewLit(pos, tok int, obj *Object) *Expr {
+// TODO probably don't need the tok parameter eventually
+export func NewLit(tok int, obj *Object) *Expr {
e := new(Expr);
- e.pos, e.tok, e.obj = pos, tok, obj;
+ e.pos, e.tok, e.obj = obj.pos, tok, obj;
return e;
}
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
+ scope *Scope; // struct fields, methods
}
// 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;
- return e;
+export func NewTypeExpr(typ *Type) *Expr {
+ obj := NewObject(typ.pos, TYPE, "");
+ obj.typ = typ;
+ return NewLit(Scanner.TYPE, obj);
}
func ExprType(x *AST.Expr) *AST.Type {
var t *AST.Type;
if x.tok == Scanner.TYPE {
- t = x.t;
+ t = x.obj.typ;
} else if x.tok == Scanner.IDENT {
// assume a type name
t = AST.NewType(x.pos, AST.TYPENAME);
if x != nil && x.tok == Scanner.TYPE {
P.Error(x.pos, "expected expression, found type");
val := AST.NewObject(x.pos, AST.NONE, "0");
- x = AST.NewLit(x.pos, Scanner.INT, val);
+ x = AST.NewLit(Scanner.INT, val);
}
return x;
}
} else {
assert(obj.kind != AST.NONE);
}
- x = AST.NewLit(P.pos, Scanner.IDENT, obj);
+ x = AST.NewLit(Scanner.IDENT, obj);
+ x.pos = P.pos; // override obj.pos (incorrect if object was looked up!)
if P.verbose {
P.PrintIndent();
print("Ident = \"", P.val, "\"\n");
}
-// TODO: The code below (ParseVarDecl, ParseVarDeclList) is all too
-// complicated. There must be a better way to do this.
-
-func (P *Parser) ParseVarDecl(expect_ident bool) *AST.Type {
+func (P *Parser) ParseVar(expect_ident bool) *AST.Type {
t := AST.BadType;
if expect_ident {
x := P.ParseIdent(nil);
}
-func (P *Parser) ParseVarDeclList(list *array.Array, ellipsis_ok bool) {
- P.Trace("VarDeclList");
+func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) {
+ P.Trace("VarList");
- // parse a list of types
+ // assume a list of types
+ // (a list of identifiers looks like a list of type names)
i0 := list.Len();
for {
- list.Push(P.ParseVarDecl(ellipsis_ok /* param list */ && i0 > 0));
+ list.Push(P.ParseVar(ellipsis_ok /* param list */ && i0 > 0));
if P.tok == Scanner.COMMA {
P.Next();
} else {
}
}
+ // if we had a list of identifiers, it must be followed by a type
typ := P.TryType();
if typ == nil && P.tok == Scanner.ELLIPSIS {
typ = AST.NewType(P.pos, AST.ELLIPSIS);
P.Trace("ParameterList");
list := array.New(0);
- P.ParseVarDeclList(list, ellipsis_ok);
+ P.ParseVarList(list, ellipsis_ok);
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseVarDeclList(list, ellipsis_ok);
+ P.ParseVarList(list, ellipsis_ok);
}
P.Ecart();
t.list = array.New(0);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
- P.ParseVarDeclList(t.list, false);
+ P.ParseVarList(t.list, false);
if P.tok == Scanner.STRING {
// ParseOperand takes care of string concatenation
t.list.Push(P.ParseOperand());
P.Trace("FunctionLit");
val := AST.NewObject(P.pos, AST.NONE, "");
- x := AST.NewLit(P.pos, Scanner.FUNC, val);
+ x := AST.NewLit(Scanner.FUNC, val);
P.Expect(Scanner.FUNC);
- x.t = P.ParseFunctionType();
+ val.typ = P.ParseFunctionType();
P.expr_lev++;
P.scope_lev++;
val.block, val.end = P.ParseBlock();
case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
val := AST.NewObject(P.pos, AST.NONE, P.val);
- x = AST.NewLit(P.pos, P.tok, val);
+ x = AST.NewLit(P.tok, val);
P.Next();
if x.tok == Scanner.STRING {
// TODO should remember the list instead of
} else {
P.Expect(Scanner.LPAREN);
- x.t = P.ParseType();
+ x.y = AST.NewTypeExpr(P.ParseType());
P.Expect(Scanner.RPAREN);
}
P.Trace("CompositeLit");
x := P.NewExpr(P.pos, Scanner.LBRACE, nil, nil);
- x.t = t;
+ x.obj = AST.NewObject(t.pos, AST.TYPE, "");
+ x.obj.typ = t;
P.Expect(Scanner.LBRACE);
if P.tok != Scanner.RBRACE {
x.y = P.ParseCompositeElements();
if tok == Scanner.MUL && y.tok == Scanner.TYPE {
// pointer type
t := AST.NewType(pos, AST.POINTER);
- t.elt = y.t;
+ t.elt = y.obj.typ;
x = AST.NewTypeExpr(t);
} else {
x = P.NewExpr(pos, tok, nil, y);
if P.tok == Scanner.STRING {
// TODO eventually the scanner should strip the quotes
val := AST.NewObject(P.pos, AST.NONE, P.val);
- d.val = AST.NewLit(P.pos, Scanner.STRING, val);
+ d.val = AST.NewLit(Scanner.STRING, val);
P.Next();
} else {
P.Expect(Scanner.STRING); // use Expect() error handling