Commit b705ac6c authored by Robert Griesemer's avatar Robert Griesemer

- composites, receivers, various add. checks

R=r
OCL=17295
CL=17295
parent 082f116b
...@@ -68,38 +68,8 @@ export func NewList() *List { ...@@ -68,38 +68,8 @@ export func NewList() *List {
} }
// ----------------------------------------------------------------------------
// Types
export const /* channel mode */ (
FULL = iota;
SEND;
RECV;
)
export type Type struct {
pos, tok int;
expr *Expr; // type name, array length
mode int; // channel mode
key *Type; // map key
elt *Type; // array element, map or channel value, or pointer base type
list *List; // struct fields, interface methods, function parameters
}
export func NewType(pos, tok int) *Type {
t := new(Type);
t.pos, t.tok = pos, tok;
return t;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
//
// Expression pairs are represented as binary expressions with operator ":"
// Expression lists are represented as binary expressions with operator ","
export type Expr struct { export type Expr struct {
pos, tok int; pos, tok int;
...@@ -135,9 +105,53 @@ export func NewLit(pos, tok int, s string) *Expr { ...@@ -135,9 +105,53 @@ export func NewLit(pos, tok int, s string) *Expr {
} }
export func NewTypeExpr(pos int, t *Type) *Expr { // ----------------------------------------------------------------------------
// Types
export const /* channel mode */ (
FULL = iota;
SEND;
RECV;
)
export type Type struct {
pos, tok int;
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
list *List; // struct fields, interface methods, function parameters
}
func (t *Type) nfields() int {
nx, nt := 0, 0;
for i, n := 0, t.list.len(); i < n; i++ {
if t.list.at(i).(*Expr).tok == Scanner.TYPE {
nt++;
} else {
nx++;
}
}
if nx == 0 {
return nt;
}
return nx;
}
export func NewType(pos, tok int) *Type {
t := new(Type);
t.pos, t.tok = pos, tok;
return t;
}
// requires complete Type type
export func NewTypeExpr(t *Type) *Expr {
e := new(Expr); e := new(Expr);
e.pos, e.tok, e.t = pos, Scanner.TYPE, t; e.pos, e.tok, e.t = t.pos, Scanner.TYPE, t;
return e; return e;
} }
......
...@@ -131,18 +131,19 @@ func (P *Parser) ParseIdent() *Node.Expr { ...@@ -131,18 +131,19 @@ func (P *Parser) ParseIdent() *Node.Expr {
} }
func (P *Parser) ParseIdentList() *Node.List { func (P *Parser) ParseIdentList() *Node.Expr {
P.Trace("IdentList"); P.Trace("IdentList");
list := Node.NewList(); x := P.ParseIdent();
list.Add(P.ParseIdent()); if P.tok == Scanner.COMMA {
for P.tok == Scanner.COMMA { pos := P.pos;
P.Next(); P.Next();
list.Add(P.ParseIdent()); y := P.ParseIdentList();
x := Node.NewExpr(pos, Scanner.COMMA, x, y);
} }
P.Ecart(); P.Ecart();
return list; return x;
} }
...@@ -241,6 +242,7 @@ func (P *Parser) ParseChannelType() *Node.Type { ...@@ -241,6 +242,7 @@ func (P *Parser) ParseChannelType() *Node.Type {
func (P *Parser) ParseVarDeclList(list *Node.List) { func (P *Parser) ParseVarDeclList(list *Node.List) {
P.Trace("VarDeclList"); P.Trace("VarDeclList");
// parse a list of types
i0 := list.len(); i0 := list.len();
list.Add(P.ParseType()); list.Add(P.ParseType());
for P.tok == Scanner.COMMA { for P.tok == Scanner.COMMA {
...@@ -250,6 +252,7 @@ func (P *Parser) ParseVarDeclList(list *Node.List) { ...@@ -250,6 +252,7 @@ func (P *Parser) ParseVarDeclList(list *Node.List) {
typ := P.TryType(); typ := P.TryType();
// convert the list into a list of (type) expressions
if typ != nil { if typ != nil {
// all list entries must be identifiers // all list entries must be identifiers
// convert the type entries into identifiers // convert the type entries into identifiers
...@@ -263,14 +266,14 @@ func (P *Parser) ParseVarDeclList(list *Node.List) { ...@@ -263,14 +266,14 @@ func (P *Parser) ParseVarDeclList(list *Node.List) {
} }
} }
// add type // add type
list.Add(Node.NewTypeExpr(typ.pos, typ)); list.Add(Node.NewTypeExpr(typ));
} else { } else {
// all list entries are types // all list entries are types
// convert all type entries into type expressions // convert all type entries into type expressions
for i, n := i0, list.len(); i < n; i++ { for i, n := i0, list.len(); i < n; i++ {
t := list.at(i).(*Node.Type); t := list.at(i).(*Node.Type);
list.set(i, Node.NewTypeExpr(t.pos, t)); list.set(i, Node.NewTypeExpr(t));
} }
if P.tok == Scanner.COMMA { if P.tok == Scanner.COMMA {
...@@ -339,7 +342,7 @@ func (P *Parser) ParseResult() *Node.Type { ...@@ -339,7 +342,7 @@ func (P *Parser) ParseResult() *Node.Type {
if typ != nil { if typ != nil {
t = Node.NewType(P.pos, Scanner.STRUCT); t = Node.NewType(P.pos, Scanner.STRUCT);
t.list = Node.NewList(); t.list = Node.NewList();
t.list.Add(Node.NewTypeExpr(typ.pos, typ)); t.list.Add(Node.NewTypeExpr(typ));
} }
} }
...@@ -572,7 +575,7 @@ func (P *Parser) ParseOperand() *Node.Expr { ...@@ -572,7 +575,7 @@ func (P *Parser) ParseOperand() *Node.Expr {
default: default:
t := P.TryType(); t := P.TryType();
if t != nil { if t != nil {
x = Node.NewTypeExpr(t.pos, t); x = Node.NewTypeExpr(t);
} else { } else {
P.Error(P.pos, "operand expected"); P.Error(P.pos, "operand expected");
P.Next(); // make progress P.Next(); // make progress
...@@ -653,31 +656,42 @@ func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr { ...@@ -653,31 +656,42 @@ func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr {
} }
func (P *Parser) ParseExpressionPairList(mode int) *Node.Expr {
P.Trace("ExpressionPairList");
x := P.ParseExpressionPair(mode);
if mode == 0 {
// first expression determines mode
if x.tok == Scanner.COLON {
mode = 2;
} else {
mode = 1;
}
}
if P.tok == Scanner.COMMA {
pos := P.pos;
P.Next();
if P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
y := P.ParseExpressionPairList(mode);
x = Node.NewExpr(pos, Scanner.COMMA, x, y);
}
}
P.Ecart();
return x;
}
func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr { func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr {
P.Trace("CompositeLit"); P.Trace("CompositeLit");
mode := 0; pos := P.pos;
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { x := P.ParseExpressionPairList(0);
x := P.ParseExpressionPair(mode);
if mode == 0 {
// first expression determines mode
if x.tok == Scanner.COLON {
mode = 2;
} else {
mode = 1;
}
}
if P.tok == Scanner.COMMA {
P.Next();
} else {
break;
}
}
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.Ecart(); P.Ecart();
return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr return Node.NewExpr(pos, Scanner.LBRACE, Node.NewTypeExpr(t), x);
} }
...@@ -780,16 +794,16 @@ func (P *Parser) ParseSimpleStat() *Node.Stat { ...@@ -780,16 +794,16 @@ func (P *Parser) ParseSimpleStat() *Node.Stat {
P.Trace("SimpleStat"); P.Trace("SimpleStat");
var s *Node.Stat; var s *Node.Stat;
x := P.ParseExpressionList(); x := P.ParseExpressionList();
switch P.tok { switch P.tok {
case Scanner.COLON: case Scanner.COLON:
// label declaration // label declaration
if x.len() == 1 { s = Node.NewStat(P.pos, Scanner.COLON);
s = Node.NewStat(P.pos, Scanner.COLON); s.expr = x;
s.expr = x; if x.len() != 1 {
} else { P.Error(x.pos, "illegal label declaration");
P.Error(P.pos, "illegal label declaration");
} }
P.Next(); // consume ":" P.Next(); // consume ":"
P.opt_semi = true; P.opt_semi = true;
...@@ -803,23 +817,22 @@ func (P *Parser) ParseSimpleStat() *Node.Stat { ...@@ -803,23 +817,22 @@ func (P *Parser) ParseSimpleStat() *Node.Stat {
P.Next(); P.Next();
s.lhs = x; s.lhs = x;
s.expr = P.ParseExpressionList(); s.expr = P.ParseExpressionList();
if l, r := x.len(), s.expr.len(); l > 1 && r > 1 && l != r {
P.Error(x.pos, "arity of lhs doesn't match rhs");
}
default: default:
var pos, tok int;
if P.tok == Scanner.INC || P.tok == Scanner.DEC { if P.tok == Scanner.INC || P.tok == Scanner.DEC {
s = Node.NewStat(P.pos, P.tok); pos, tok = P.pos, P.tok;
if x.len() == 1 { P.Next();
s.expr = x;
} else {
P.Error(P.pos, "more then one operand");
}
P.Next(); // consume "++" or "--"
} else { } else {
s = Node.NewStat(P.pos, 0); // TODO give this a token value pos, tok = x.pos, 0; // TODO give this a token value
if x.len() == 1 { }
s.expr = x; s = Node.NewStat(pos, tok);
} else { s.expr = x;
P.Error(P.pos, "syntax error"); if x.len() != 1 {
} P.Error(x.pos, "only one expression allowed");
} }
} }
...@@ -1173,15 +1186,15 @@ func (P *Parser) ParseVarSpec(exported bool) *Node.Decl { ...@@ -1173,15 +1186,15 @@ func (P *Parser) ParseVarSpec(exported bool) *Node.Decl {
P.Trace("VarSpec"); P.Trace("VarSpec");
d := Node.NewDecl(P.pos, Scanner.VAR, exported); d := Node.NewDecl(P.pos, Scanner.VAR, exported);
P.ParseIdentList(); d.ident = P.ParseIdentList();
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); d.val = P.ParseExpressionList();
} else { } else {
P.ParseVarType(); d.typ = P.ParseVarType();
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); d.val = P.ParseExpressionList();
} }
} }
...@@ -1246,20 +1259,20 @@ func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl { ...@@ -1246,20 +1259,20 @@ func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl {
d := Node.NewDecl(P.pos, Scanner.FUNC, exported); d := Node.NewDecl(P.pos, Scanner.FUNC, exported);
P.Expect(Scanner.FUNC); P.Expect(Scanner.FUNC);
var recv *Node.Type;
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
pos := P.pos; pos := P.pos;
recv := P.ParseParameters(); recv = P.ParseParameters();
// TODO: fix this if recv.nfields() != 1 {
/*
if recv.list.len() != 1 {
P.Error(pos, "must have exactly one receiver"); P.Error(pos, "must have exactly one receiver");
} }
*/
} }
d.ident = P.ParseIdent(); d.ident = P.ParseIdent();
d.typ = P.ParseFunctionType(); d.typ = P.ParseFunctionType();
d.typ.key = recv;
if P.tok == Scanner.LBRACE { if P.tok == Scanner.LBRACE {
P.scope_lev++; P.scope_lev++;
d.list = P.ParseBlock(); d.list = P.ParseBlock();
......
...@@ -70,7 +70,8 @@ func (P *Printer) CloseScope(paren string) { ...@@ -70,7 +70,8 @@ func (P *Printer) CloseScope(paren string) {
func (P *Printer) Type(t *Node.Type) func (P *Printer) Type(t *Node.Type)
func (P *Printer) Expr(x *Node.Expr) func (P *Printer) Expr(x *Node.Expr)
func (P *Printer) Parameters(list *Node.List) { func (P *Printer) Parameters(pos int, list *Node.List) {
P.String(pos, "(");
var prev int; var prev int;
for i, n := 0, list.len(); i < n; i++ { for i, n := 0, list.len(); i < n; i++ {
x := list.at(i).(*Node.Expr); x := list.at(i).(*Node.Expr);
...@@ -84,6 +85,7 @@ func (P *Printer) Parameters(list *Node.List) { ...@@ -84,6 +85,7 @@ func (P *Printer) Parameters(list *Node.List) {
P.Expr(x); P.Expr(x);
prev = x.tok; prev = x.tok;
} }
P.String(0, ")");
} }
...@@ -123,7 +125,7 @@ func (P *Printer) Type(t *Node.Type) { ...@@ -123,7 +125,7 @@ func (P *Printer) Type(t *Node.Type) {
if t.expr != nil { if t.expr != nil {
P.Expr(t.expr); P.Expr(t.expr);
} }
P.String(0, "] "); P.String(0, "]");
P.Type(t.elt); P.Type(t.elt);
case Scanner.STRUCT: case Scanner.STRUCT:
...@@ -137,7 +139,7 @@ func (P *Printer) Type(t *Node.Type) { ...@@ -137,7 +139,7 @@ func (P *Printer) Type(t *Node.Type) {
case Scanner.MAP: case Scanner.MAP:
P.String(t.pos, "["); P.String(t.pos, "[");
P.Type(t.key); P.Type(t.key);
P.String(0, "] "); P.String(0, "]");
P.Type(t.elt); P.Type(t.elt);
case Scanner.CHAN: case Scanner.CHAN:
...@@ -168,13 +170,10 @@ func (P *Printer) Type(t *Node.Type) { ...@@ -168,13 +170,10 @@ func (P *Printer) Type(t *Node.Type) {
P.Type(t.elt); P.Type(t.elt);
case Scanner.LPAREN: case Scanner.LPAREN:
P.String(t.pos, "("); P.Parameters(t.pos, t.list);
P.Parameters(t.list);
P.String(0, ")");
if t.elt != nil { if t.elt != nil {
P.String(0, " ("); P.Blank();
P.Parameters(t.elt.list); P.Parameters(0, t.elt.list);
P.String(0, ")");
} }
default: default:
...@@ -192,9 +191,6 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) { ...@@ -192,9 +191,6 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) {
} }
switch x.tok { switch x.tok {
case Scanner.VAR:
panic("UNIMPLEMENTED (VAR)");
case Scanner.TYPE: case Scanner.TYPE:
P.Type(x.t); P.Type(x.t);
...@@ -222,6 +218,12 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) { ...@@ -222,6 +218,12 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) {
P.String(x.pos, "("); P.String(x.pos, "(");
P.Expr1(x.y, 0); P.Expr1(x.y, 0);
P.String(0, ")"); P.String(0, ")");
case Scanner.LBRACE:
P.Expr1(x.x, 8);
P.String(x.pos, "{");
P.Expr1(x.y, 0);
P.String(0, "}");
default: default:
if x.x == nil { if x.x == nil {
...@@ -396,35 +398,6 @@ func (P *Printer) Stat(s *Node.Stat) { ...@@ -396,35 +398,6 @@ func (P *Printer) Stat(s *Node.Stat) {
// Declarations // Declarations
/*
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
if x.typ.recv != nil {
P.String("(");
P.DoVarDeclList(x.typ.recv);
P.String(") ");
}
P.DoIdent(x.ident);
P.DoFunctionType(x.typ);
if x.body != nil {
P.String(" ");
P.DoBlock(x.body);
} else {
P.String(" ;");
}
P.NewLine();
P.NewLine();
}
func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
//P.DoIdent(x.ident);
//P.DoFunctionType(x.typ);
}
*/
func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) { func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
if d == nil { // TODO remove this check if d == nil { // TODO remove this check
P.String(0, "<nil decl>"); P.String(0, "<nil decl>");
...@@ -448,6 +421,11 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) { ...@@ -448,6 +421,11 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
P.CloseScope(")"); P.CloseScope(")");
} else { } else {
if d.tok == Scanner.FUNC && d.typ.key != nil {
P.Parameters(0, d.typ.key.list);
P.Blank();
}
P.Expr(d.ident); P.Expr(d.ident);
if d.typ != nil { if d.typ != nil {
...@@ -471,6 +449,10 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) { ...@@ -471,6 +449,10 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
P.Blank(); P.Blank();
P.Block(d.list, true); P.Block(d.list, true);
} }
if d.tok != Scanner.TYPE {
P.semi = true;
}
} }
P.newl = 1; P.newl = 1;
......
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