DoNil(x *Nil);
DoIdent(x *Ident);
+ // Types
+ DoFunctionType(x *FunctionType);
+
// Declarations
+ //DoVarDeclList(x *VarDeclList);
DoFuncDecl(x *FuncDecl);
// Expressions
DoBlock(x *Block);
DoExprStat(x *ExprStat);
DoAssignment(x *Assignment);
- DoIf(x *If);
- DoFor(x *For);
+ DoIfStat(x *IfStat);
+ DoForStat(x *ForStat);
DoSwitch(x *Switch);
DoReturn(x *Return);
func (x *Ident) Visit(v Visitor) { v.DoIdent(x); }
+// ----------------------------------------------------------------------------
+// Types
+
+export type Type interface {
+ Visit(x Visitor);
+}
+
+
+export type FunctionType struct {
+ recv *VarDeclList;
+ params *List;
+ result *List;
+}
+
+
+func (x *FunctionType) Visit(v Visitor) { v.DoFunctionType(x); }
+
+
// ----------------------------------------------------------------------------
// Declarations
}
+export type VarDeclList struct {
+ idents *List;
+ typ *Node;
+}
+
+
export type FuncDecl struct {
pos int;
ident *Ident;
+ typ *FunctionType;
body *Block;
}
-func (x *FuncDecl) Visit(v Visitor) { v.DoFuncDecl(x); }
+func (x *VarDeclList) Visit(v Visitor) { /*v.DoVarDeclList(x);*/ }
+func (x *FuncDecl) Visit(v Visitor) { v.DoFuncDecl(x); }
// ----------------------------------------------------------------------------
}
-export type If struct {
+export type IfStat struct {
pos int;
+ init Stat;
cond Expr;
then, else_ *Block;
}
-export type For struct {
+export type ForStat struct {
+ pos int;
+ body *Block;
}
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); }
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); }
-func (x *If) Visit(v Visitor) { v.DoIf(x); }
-func (x *For) Visit(v Visitor) { v.DoFor(x); }
+func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); }
+func (x *ForStat) Visit(v Visitor) { v.DoForStat(x); }
func (x *Switch) Visit(v Visitor) { v.DoSwitch(x); }
func (x *Return) Visit(v Visitor) { v.DoReturn(x); }
}
-func (P *Parser) ParseIdentList() int {
+func (P *Parser) ParseIdentList() *AST.List {
P.Trace("IdentList");
- P.ParseIdent();
- n := 1;
+ list := AST.NewList();
+ list.Add(P.ParseIdent());
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseIdent();
- n++;
+ list.Add(P.ParseIdent());
}
P.Ecart();
- return n;
+ return list;
}
}
-func (P *Parser) ParseVarDeclList() int {
+func (P *Parser) ParseVarDeclList() *AST.VarDeclList {
P.Trace("VarDeclList");
- n := P.ParseIdentList();
+ res := new(AST.VarDeclList);
+ res.idents = P.ParseIdentList();
P.ParseVarType();
P.Ecart();
- return n;
+ return res;
}
-func (P *Parser) ParseParameterList() int {
+// Returns a list of AST.VarDeclList
+func (P *Parser) ParseParameterList() *AST.List {
P.Trace("ParameterList");
- n := P.ParseVarDeclList();
+ list := AST.NewList();
+ list.Add(P.ParseVarDeclList());
for P.tok == Scanner.COMMA {
P.Next();
- n += P.ParseVarDeclList();
+ list.Add(P.ParseVarDeclList());
}
P.Ecart();
- return n;
+ return list;
}
-func (P *Parser) ParseParameters() int {
+// Returns a list of AST.VarDeclList
+func (P *Parser) ParseParameters() *AST.List {
P.Trace("Parameters");
- n := 0;
+ var list *AST.List;
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
- n = P.ParseParameterList();
+ list = P.ParseParameterList();
}
P.Expect(Scanner.RPAREN);
P.Ecart();
- return n;
+ return list;
}
}
-func (P *Parser) ParseResult() {
+func (P *Parser) ParseResult() *AST.List {
P.Trace("Result");
if P.tok == Scanner.LPAREN {
}
P.Ecart();
+ return nil
}
// (params) type
// (params) (results)
-func (P *Parser) ParseFunctionType() {
+func (P *Parser) ParseFunctionType() *AST.FunctionType {
P.Trace("FunctionType");
P.OpenScope();
P.level--;
- P.ParseParameters();
- P.ParseResult();
+ typ := new(AST.FunctionType);
+ typ.params = P.ParseParameters();
+ typ.result = P.ParseResult();
P.level++;
P.CloseScope();
P.Ecart();
+ return typ;
}
}
-func (P *Parser) ParseIfStat() *AST.If {
+func (P *Parser) ParseIfStat() *AST.IfStat {
P.Trace("IfStat");
- x := new(AST.If);
+ x := new(AST.IfStat);
x.pos, x.cond = P.pos, AST.NIL;
+ var init, cond AST.Node = AST.NIL, AST.NIL;
P.Expect(Scanner.IF);
P.OpenScope();
if P.tok != Scanner.LBRACE {
if P.tok != Scanner.SEMICOLON {
- P.ParseSimpleStat();
+ init = P.ParseSimpleStat();
}
if P.tok == Scanner.SEMICOLON {
P.Next();
if P.tok != Scanner.LBRACE {
- x.cond = P.ParseExpression();
+ cond = P.ParseExpression();
+ } else {
+ cond = init;
+ init = AST.NIL;
}
}
}
+ x.init, x.cond = init, cond;
+
x.then = P.ParseBlock();
if P.tok == Scanner.ELSE {
P.Next();
}
-func (P *Parser) ParseForStat() {
+func (P *Parser) ParseForStat() *AST.ForStat {
P.Trace("ForStat");
+ stat := new(AST.ForStat);
+ stat.pos = P.pos;
+
P.Expect(Scanner.FOR);
P.OpenScope();
if P.tok != Scanner.LBRACE {
}
}
}
- P.ParseBlock();
+ stat.body = P.ParseBlock();
P.CloseScope();
P.Ecart();
+ return stat;
}
case Scanner.IF:
stat = P.ParseIfStat();
case Scanner.FOR:
- P.ParseForStat();
+ stat = P.ParseForStat();
case Scanner.SWITCH:
P.ParseSwitchStat();
case Scanner.RANGE:
func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl {
P.Trace("FuncDecl");
- pos := P.pos;
+ fun := new(AST.FuncDecl);
+ fun.pos = P.pos;
+
P.Expect(Scanner.FUNC);
P.OpenScope();
P.level--;
+ var recv *AST.VarDeclList;
if P.tok == Scanner.LPAREN {
recv_pos := P.pos;
- n := P.ParseParameters();
+ recv := P.ParseParameters().at(0);
+ /*
if n != 1 {
P.Error(recv_pos, "must have exactly one receiver");
}
+ */
}
- ident := P.ParseIdent();
-
- P.ParseFunctionType();
+ fun.ident = P.ParseIdent();
+ fun.typ = P.ParseFunctionType();
+ fun.typ.recv = recv;
P.level++;
P.CloseScope();
- var body *AST.Block;
if P.tok == Scanner.SEMICOLON {
// forward declaration
P.Next();
} else {
- body = P.ParseBlock();
+ fun.body = P.ParseBlock();
}
P.Ecart();
- x := new(AST.FuncDecl);
- x.pos, x.ident, x.body = pos, ident, body;
- return x;
+ return fun;
}
}
+func (P *Printer) NewLine(delta int) {
+ P.indent += delta;
+ if P.indent < 0 {
+ panic("negative indent");
+ }
+ print("\n");
+ for i := P.indent; i > 0; i-- {
+ print("\t");
+ }
+}
+
+
func (P *Printer) String(s string) {
print(s);
}
}
-func (P *Printer) PrintExprList(p *AST.List) {
+func (P *Printer) PrintList(p *AST.List) {
if p != nil {
for i := 0; i < p.len(); i++ {
if i > 0 {
// Basics
func (P *Printer) DoNil(x *AST.Nil) {
- P.String("?\n");
+ P.String("?");
+ P.NewLine(0);
}
}
+// ----------------------------------------------------------------------------
+// Types
+
+func (P *Printer) DoFunctionType(x *AST.FunctionType) {
+ /*
+ if x.recv != nil {
+ P.DoVarDeclList(x.recv);
+ }
+ */
+ P.String("(");
+ P.PrintList(x.params);
+ P.String(") ");
+}
+
+
// ----------------------------------------------------------------------------
// Declarations
func (P *Printer) DoBlock(x *AST.Block);
+
+//func (P *Printer) DoVarDeclList(x *VarDeclList) {
+//}
+
+
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
+ if x.typ.recv != nil {
+ P.String("(");
+ P.PrintList(x.typ.recv.idents);
+ P.String(") ");
+ }
P.DoIdent(x.ident);
- P.String("(... something here ...) ");
+ P.DoFunctionType(x.typ);
if x.body != nil {
P.DoBlock(x.body);
} else {
- P.String(";\n");
+ P.String(";");
}
+ P.NewLine(0);
+ P.NewLine(0);
+ P.NewLine(0);
}
func (P *Printer) DoCall(x *AST.Call) {
P.Print(x.fun);
P.String("(");
- P.PrintExprList(x.args);
+ P.PrintList(x.args);
P.String(")");
}
func (P *Printer) DoBlock(x *AST.Block) {
if x == nil || x.stats == nil {
- P.String("\n");
+ P.NewLine(0);
return;
}
- P.String("{\n");
- P.indent++;
+ P.String("{");
+ P.NewLine(1);
for i := 0; i < x.stats.len(); i++ {
+ if i > 0 {
+ P.NewLine(0);
+ }
P.Print(x.stats.at(i));
- P.String("\n");
}
- P.indent--;
- P.String("}\n");
+ P.NewLine(-1);
+ P.String("}");
}
func (P *Printer) DoExprStat(x *AST.ExprStat) {
P.Print(x.expr);
+ P.String(";");
}
func (P *Printer) DoAssignment(x *AST.Assignment) {
- P.PrintExprList(x.lhs);
+ P.PrintList(x.lhs);
P.String(" " + Scanner.TokenName(x.tok) + " ");
- P.PrintExprList(x.rhs);
+ P.PrintList(x.rhs);
+ P.String(";");
}
-func (P *Printer) DoIf(x *AST.If) {
+func (P *Printer) DoIfStat(x *AST.IfStat) {
P.String("if ");
+ P.Print(x.init);
+ P.String("; ");
P.Print(x.cond);
P.DoBlock(x.then);
if x.else_ != nil {
- P.String("else ");
+ P.String(" else ");
P.DoBlock(x.else_);
}
}
-func (P *Printer) DoFor(x *AST.For) {
+func (P *Printer) DoForStat(x *AST.ForStat) {
+ P.String("for ");
+ P.DoBlock(x.body);
}
func (P *Printer) DoSwitch(x *AST.Switch) {
+ P.String("switch ");
}
func (P *Printer) DoReturn(x *AST.Return) {
P.String("return ");
- P.PrintExprList(x.res);
+ P.PrintList(x.res);
+ P.String(";");
}
func (P *Printer) DoProgram(x *AST.Program) {
P.String("package ");
P.DoIdent(x.ident);
- P.String("\n");
+ P.NewLine(0);
for i := 0; i < x.decls.len(); i++ {
P.Print(x.decls.at(i));
}