- more work on semantic checks - not yet enabled by default

R=r
OCL=13391
CL=13391
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 28fdf39..c40b70b 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -126,11 +126,7 @@
 
 
 func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
-	if !EnableSemanticTests {
-		return;
-	}
-	
-	if scope.Lookup(obj.ident) != nil {
+	if EnableSemanticTests && scope.Lookup(obj.ident) != nil {
 		// TODO is this the correct error position?
 		P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
 		return;  // don't insert it into the scope
@@ -283,63 +279,92 @@
 
 func (P *Parser) ParseArrayType() *Globals.Type {
 	P.Trace("ArrayType");
+	
 	P.Expect(Scanner.LBRACK);
+	typ := Globals.NewType(Type.ARRAY);
 	if P.tok != Scanner.RBRACK {
+		// TODO set typ.len_
 		P.ParseExpression();
 	}
 	P.Expect(Scanner.RBRACK);
-	P.ParseType();
+	typ.elt = P.ParseType();
 	P.Ecart();
-	return Universe.bad_t;
+	
+	return typ;
 }
 
 
 func (P *Parser) ParseChannelType() *Globals.Type {
 	P.Trace("ChannelType");
+	
 	P.Expect(Scanner.CHAN);
+	typ := Globals.NewType(Type.CHANNEL);
 	switch P.tok {
-	case Scanner.SEND: fallthrough
-	case Scanner.RECV:
+	case Scanner.SEND:
+		typ.flags = Type.SEND;
 		P.Next();
+	case Scanner.RECV:
+		typ.flags = Type.RECV;
+		P.Next();
+	default:
+		typ.flags = Type.SEND + Type.RECV;
 	}
-	P.ParseType();
+	typ.elt = P.ParseType();
 	P.Ecart();
-	return Universe.bad_t;
+	
+	return typ;
+}
+
+
+func (P *Parser) ParseVarDeclList() {
+	P.Trace("VarDeclList");
+	
+	list := P.ParseIdentDeclList(Object.VAR);
+	typ := P.ParseType();  // TODO should check completeness of types
+	for p := list.first; p != nil; p = p.next {
+		p.obj.typ = typ;  // TODO should use/have set_type()
+	}
+	
+	P.Ecart();
 }
 
 
 func (P *Parser) ParseParameterSection() {
 	P.Trace("ParameterSection");
-	P.ParseIdentList();
-	P.ParseType();
+	P.ParseVarDeclList();
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseParameterList() {
 	P.Trace("ParameterList");
+	
 	P.ParseParameterSection();
 	for P.tok == Scanner.COMMA {
 		P.Next();
 		P.ParseParameterSection();
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseParameters() {
 	P.Trace("Parameters");
+	
 	P.Expect(Scanner.LPAREN);
 	if P.tok != Scanner.RPAREN {
 		P.ParseParameterList();
 	}
 	P.Expect(Scanner.RPAREN);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) TryResult() bool {
 	P.Trace("Result (try)");
+	
 	res := false;
 	if P.tok == Scanner.LPAREN {
 		// TODO: here we allow empty returns - should proably fix this
@@ -349,10 +374,31 @@
 		res = P.TryType() != nil;
 	}
 	P.Ecart();
+	
 	return res;
 }
 
 
+func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
+  // Determine if we have a receiver or not.
+  if p0 > 0 && check_recv {
+    // method
+	if p0 != 1 {
+		panic "p0 != 1";
+	}
+  }
+  typ := Globals.NewType(Type.FUNCTION);
+  if p0 == 0 {
+	typ.flags = 0;
+  } else {
+	typ.flags = Type.RECV;
+  }
+  typ.len_ = r0 - p0;
+  typ.scope = sig;
+  return typ;
+}
+
+
 // Anonymous signatures
 //
 //          (params)
@@ -362,17 +408,33 @@
 // (recv) . (params) type
 // (recv) . (params) (results)
 
-func (P *Parser) ParseAnonymousSignature() {
+func (P *Parser) ParseAnonymousSignature() *Globals.Type {
 	P.Trace("AnonymousSignature");
+	
 	P.OpenScope();
+	sig := P.top_scope;
+	p0 := 0;
+	
+	recv_pos := P.pos;
 	P.ParseParameters();
+	
 	if P.tok == Scanner.PERIOD {
+		p0 = sig.entries.len_;
+		if (p0 != 1) {
+			P.Error(recv_pos, "must have exactly one receiver")
+			panic "UNIMPLEMENTED";
+			// TODO do something useful here
+		}
 		P.Next();
 		P.ParseParameters();
 	}
+	
+	r0 := sig.entries.len_;
 	P.TryResult();
 	P.CloseScope();
+	
 	P.Ecart();
+	return MakeFunctionType(sig, p0, r0, true);
 }
 
 
@@ -385,75 +447,97 @@
 // (recv) name (params) type
 // (recv) name (params) (results)
 
-func (P *Parser) ParseNamedSignature() {
+func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
 	P.Trace("NamedSignature");
+	
 	P.OpenScope();
+	sig := P.top_scope;
+	p0 := 0;
+
 	if P.tok == Scanner.LPAREN {
+		recv_pos := P.pos;
 		P.ParseParameters();
+		p0 = sig.entries.len_;
+		if (p0 != 1) {
+			print "p0 = ", p0, "\n";
+			P.Error(recv_pos, "must have exactly one receiver")
+			panic "UNIMPLEMENTED";
+			// TODO do something useful here
+		}
 	}
-	P.ParseIdent();  // function name
+	
+	name = P.ParseIdent();
+
 	P.ParseParameters();
+	
+	r0 := sig.entries.len_;
 	P.TryResult();
 	P.CloseScope();
-	P.Ecart();
+	
+	return name, MakeFunctionType(sig, p0, r0, true);
 }
 
 
 func (P *Parser) ParseFunctionType() *Globals.Type {
 	P.Trace("FunctionType");
+	
 	P.Expect(Scanner.FUNC);
-	P.ParseAnonymousSignature();
+	typ := P.ParseAnonymousSignature();
+	
 	P.Ecart();
-	return Universe.bad_t;
+	return typ;
 }
 
 
 func (P *Parser) ParseMethodDecl() {
 	P.Trace("MethodDecl");
+	
 	P.ParseIdent();
 	P.ParseParameters();
 	P.TryResult();
 	P.Optional(Scanner.SEMICOLON);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseInterfaceType() *Globals.Type {
 	P.Trace("InterfaceType");
+	
 	P.Expect(Scanner.INTERFACE);
 	P.Expect(Scanner.LBRACE);
 	P.OpenScope();
+	typ := Globals.NewType(Type.INTERFACE);
+	typ.scope = P.top_scope;
 	for P.tok != Scanner.RBRACE {
 		P.ParseMethodDecl();
 	}
 	P.CloseScope();
 	P.Next();
+	
 	P.Ecart();
-	return Universe.bad_t;
+	return typ;
 }
 
 
 func (P *Parser) ParseMapType() *Globals.Type {
 	P.Trace("MapType");
+	
 	P.Expect(Scanner.MAP);
 	P.Expect(Scanner.LBRACK);
-	P.ParseType();
+	typ := Globals.NewType(Type.MAP);
+	typ.key = P.ParseType();
 	P.Expect(Scanner.RBRACK);
-	P.ParseType();
+	typ.elt = P.ParseType();
 	P.Ecart();
-	return Universe.bad_t;
+	
+	return typ;
 }
 
 
 func (P *Parser) ParseFieldDecl() {
 	P.Trace("FieldDecl");
-	
-	list := P.ParseIdentDeclList(Object.VAR);
-	typ := P.ParseType();  // TODO should check completeness of types
-	for p := list.first; p != nil; p = p.next {
-		p.obj.typ = typ;  // TODO should use/have set_type()
-	}
-	
+	P.ParseVarDeclList();
 	P.Ecart();
 }
 
@@ -483,10 +567,19 @@
 
 func (P *Parser) ParsePointerType() *Globals.Type {
 	P.Trace("PointerType");
+	
 	P.Expect(Scanner.MUL);
-	P.ParseType();
-	P.Ecart();
-	return Universe.bad_t;
+	typ := Universe.undef_t;
+	if (EnableSemanticTests && P.tok == Scanner.IDENT && P.Lookup(P.val) == nil) {
+		// forward declaration
+		panic "UNIMPLEMENTED *forward_declared_type";
+	} else {
+		typ = Globals.NewType(Type.POINTER);
+		typ.elt = P.ParseType();
+	}
+
+	P.Ecart();	
+	return typ;
 }
 
 
@@ -535,6 +628,7 @@
 
 func (P *Parser) ParseBlock() {
 	P.Trace("Block");
+	
 	P.Expect(Scanner.LBRACE);
 	P.OpenScope();
 	if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
@@ -543,6 +637,7 @@
 	P.Optional(Scanner.SEMICOLON);
 	P.CloseScope();
 	P.Expect(Scanner.RBRACE);
+	
 	P.Ecart();
 }
 
@@ -552,17 +647,20 @@
 
 func (P *Parser) ParseExpressionList() {
 	P.Trace("ExpressionList");
+	
 	P.ParseExpression();
 	for P.tok == Scanner.COMMA {
 		P.Next();
 		P.ParseExpression();
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseNew() {
 	P.Trace("New");
+	
 	P.Expect(Scanner.NEW);
 	P.Expect(Scanner.LPAREN);
 	P.ParseType();
@@ -571,20 +669,24 @@
 		P.ParseExpressionList()
 	}
 	P.Expect(Scanner.RPAREN);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseFunctionLit() {
 	P.Trace("FunctionLit");
+	
 	P.ParseFunctionType();
 	P.ParseBlock();
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseOperand() {
 	P.Trace("Operand");
+	
 	switch P.tok {
 	case Scanner.IDENT:
 		P.ParseQualifiedIdent();
@@ -607,12 +709,14 @@
 		P.Error(P.pos, "operand expected");
 		P.Next();  // make progress
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseSelectorOrTypeAssertion() {
 	P.Trace("SelectorOrTypeAssertion");
+	
 	P.Expect(Scanner.PERIOD);
 	if P.tok == Scanner.IDENT {
 		P.ParseIdent();
@@ -621,12 +725,14 @@
 		P.ParseType();
 		P.Expect(Scanner.RPAREN);
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseIndexOrSlice() {
 	P.Trace("IndexOrSlice");
+	
 	P.Expect(Scanner.LBRACK);
 	P.ParseExpression();
 	if P.tok == Scanner.COLON {
@@ -634,23 +740,27 @@
 		P.ParseExpression();
 	}
 	P.Expect(Scanner.RBRACK);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseInvocation() {
 	P.Trace("Invocation");
+	
 	P.Expect(Scanner.LPAREN);
 	if P.tok != Scanner.RPAREN {
 		P.ParseExpressionList();
 	}
 	P.Expect(Scanner.RPAREN);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParsePrimaryExpr() {
 	P.Trace("PrimaryExpr");
+	
 	P.ParseOperand();
 	for {
 		switch P.tok {
@@ -665,23 +775,27 @@
 			return;
 		}
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParsePrimaryExprList() {
 	P.Trace("PrimaryExprList");
+	
 	P.ParsePrimaryExpr();
 	for P.tok == Scanner.COMMA {
 		P.Next();
 		P.ParsePrimaryExpr();
 	}
+	
 	P.Ecart();
 }
 
 
-func (P *Parser) ParseUnaryExpr() *AST.Expr {
+func (P *Parser) ParseUnaryExpr() AST.Expr {
 	P.Trace("UnaryExpr");
+	
 	switch P.tok {
 	case Scanner.ADD: fallthrough;
 	case Scanner.SUB: fallthrough;
@@ -696,6 +810,7 @@
 		return nil;  // TODO fix this
 	}
 	P.ParsePrimaryExpr();
+	
 	P.Ecart();
 	return nil;  // TODO fix this
 }
@@ -721,13 +836,13 @@
 }
 
 
-func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr {
+func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
 	P.Trace("BinaryExpr");
 	
 	x := P.ParseUnaryExpr();
 	for prec := Precedence(P.tok); prec >= prec1; prec-- {
 		for Precedence(P.tok) == prec {
-			e := new(AST.Expr);
+			e := new(AST.BinaryExpr);
 			e.typ = Universe.undef_t;  // TODO fix this
 			e.op = P.tok;  // TODO should we use tokens or separate operator constants?
 			e.x = x;
@@ -744,7 +859,9 @@
 func (P *Parser) ParseExpression() {
 	P.Trace("Expression");
 	indent := P.indent;
+	
 	P.ParseBinaryExpr(1);
+	
 	if indent != P.indent {
 		panic "imbalanced tracing code";
 	}
@@ -809,26 +926,31 @@
 
 func (P *Parser) ParseReturnStat() {
 	P.Trace("ReturnStat");
+	
 	P.Expect(Scanner.RETURN);
 	if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
 		P.ParseExpressionList();
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseControlFlowStat(tok int) {
 	P.Trace("ControlFlowStat");
+	
 	P.Expect(tok);
 	if P.tok == Scanner.IDENT {
 		P.ParseIdent();
 	}
+	
 	P.Ecart();
 }
 
 
-func (P *Parser) ParseIfStat() {
+func (P *Parser) ParseIfStat() *AST.IfStat {
 	P.Trace("IfStat");
+	
 	P.Expect(Scanner.IF);
 	P.OpenScope();
 	if P.tok != Scanner.LBRACE {
@@ -853,12 +975,14 @@
 		}
 	}
 	P.CloseScope();
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseForStat() {
 	P.Trace("ForStat");
+	
 	P.Expect(Scanner.FOR);
 	P.OpenScope();
 	if P.tok != Scanner.LBRACE {
@@ -878,12 +1002,14 @@
 	}
 	P.ParseBlock();
 	P.CloseScope();
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseCase() {
 	P.Trace("Case");
+	
 	if P.tok == Scanner.CASE {
 		P.Next();
 		P.ParseExpressionList();
@@ -891,22 +1017,26 @@
 		P.Expect(Scanner.DEFAULT);
 	}
 	P.Expect(Scanner.COLON);
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseCaseList() {
 	P.Trace("CaseList");
+	
 	P.ParseCase();
 	for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
 		P.ParseCase();
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseCaseClause() {
 	P.Trace("CaseClause");
+	
 	P.ParseCaseList();
 	if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
 		P.ParseStatementList();
@@ -916,12 +1046,14 @@
 		P.Next();
 		P.Optional(Scanner.SEMICOLON);
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseSwitchStat() {
 	P.Trace("SwitchStat");
+	
 	P.Expect(Scanner.SWITCH);
 	P.OpenScope();
 	if P.tok != Scanner.LBRACE {
@@ -941,12 +1073,14 @@
 	}
 	P.Expect(Scanner.RBRACE);
 	P.CloseScope();
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseCommCase() {
   P.Trace("CommCase");
+  
   if P.tok == Scanner.CASE {
 	P.Next();
 	if P.tok == Scanner.GTR {
@@ -968,40 +1102,47 @@
 	P.Expect(Scanner.DEFAULT);
   }
   P.Expect(Scanner.COLON);
+  
   P.Ecart();
 }
 
 
 func (P *Parser) ParseCommClause() {
 	P.Trace("CommClause");
+	
 	P.ParseCommCase();
 	if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
 		P.ParseStatementList();
 		P.Optional(Scanner.SEMICOLON);
 	}
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseRangeStat() bool {
 	P.Trace("RangeStat");
+	
 	P.Expect(Scanner.RANGE);
 	P.ParseIdentList();
 	P.Expect(Scanner.DEFINE);
 	P.ParseExpression();
 	P.ParseBlock();
+	
 	P.Ecart();
 }
 
 
 func (P *Parser) ParseSelectStat() bool {
 	P.Trace("SelectStat");
+	
 	P.Expect(Scanner.SELECT);
 	P.Expect(Scanner.LBRACE);
 	for P.tok != Scanner.RBRACE {
 		P.ParseCommClause();
 	}
 	P.Next();
+	
 	P.Ecart();
 }
 
@@ -1009,6 +1150,7 @@
 func (P *Parser) TryStatement() bool {
 	P.Trace("Statement (try)");
 	indent := P.indent;
+
 	res := true;
 	switch P.tok {
 	case Scanner.CONST: fallthrough;
@@ -1050,6 +1192,7 @@
 		// no statement found
 		res = false;
 	}
+
 	if indent != P.indent {
 		panic "imbalanced tracing code"
 	}