~mna/snow unlisted

8286de0da7906b11bd64df48d81434c3212b1e7f — Martin Angers 1 year, 1 month ago e776a55
pkg/compiler: more parser tests
M go.mod => go.mod +4 -1
@@ 2,4 2,7 @@ module git.sr.ht/~mna/snow

go 1.13

require golang.org/x/exp v0.0.0-20191129062945-2f5052295587
require (
	github.com/kylelemons/godebug v1.1.0
	golang.org/x/exp v0.0.0-20191129062945-2f5052295587
)

M go.sum => go.sum +2 -0
@@ 1,6 1,8 @@
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

M pkg/compiler/ast.go => pkg/compiler/ast.go +4 -4
@@ 16,7 16,7 @@ func (f *file) Pos() gotoken.Pos {
		min = f.stmts[0].Pos()
	}
	if len(f.comments) > 0 {
		if p := f.comments[0].Pos(); p < min {
		if p := f.comments[0].Pos(); p < min || !min.IsValid() {
			min = p
		}
	}


@@ 29,7 29,7 @@ func (f *file) End() gotoken.Pos {
		max = f.stmts[l-1].End()
	}
	if l := len(f.comments); l > 0 {
		if p := f.comments[l-1].End(); p > max {
		if p := f.comments[l-1].End(); p > max || !max.IsValid() {
			max = p
		}
	}


@@ 57,7 57,7 @@ type fnSig struct {

func (f *fnSig) Pos() gotoken.Pos { return f.lparen }
func (f *fnSig) End() gotoken.Pos {
	if f.rarrow == gotoken.NoPos {
	if !f.rarrow.IsValid() {
		return f.rparen + 1
	}
	return f.retTyp.End()


@@ 72,7 72,7 @@ type paramDef struct {

func (p *paramDef) Pos() gotoken.Pos { return p.name.Pos() }
func (p *paramDef) End() gotoken.Pos {
	if p.comma != gotoken.NoPos {
	if p.comma.IsValid() {
		return p.comma + 1
	}
	return p.typ.End()

M pkg/compiler/parser.go => pkg/compiler/parser.go +6 -4
@@ 91,10 91,12 @@ func (p *parser) advance(to map[token]bool) {
func (p *parser) parseFile() *file {
	// TODO: scopes

	// stop if we had errors scanning the first token, likely not a valid source file.
	if p.errors.Len() != 0 {
		return nil
	}
	/*
		// stop if we had errors scanning the first token, likely not a valid source file.
		if p.errors.Len() != 0 {
			return nil
		}
	*/

	var stmts []stmt
	for p.tok != EOF {

M pkg/compiler/parser_test.go => pkg/compiler/parser_test.go +47 -6
@@ 2,13 2,19 @@ package compiler

import (
	"bytes"
	"fmt"
	"flag"
	goscanner "go/scanner"
	gotoken "go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/kylelemons/godebug/diff"
)

var testUpdateParserTests = flag.Bool("test.update-parser-tests", false, "If set, replace expected parser test results with actual results.")

func TestParser(t *testing.T) {
	fis, err := ioutil.ReadDir("testdata")
	if err != nil {


@@ 35,17 41,52 @@ func TestParser(t *testing.T) {
			p.init(fset, fi.Name(), b)

			f := p.parseFile()
			if err := p.errors.Err(); err != nil {
				t.Fatal(err)
			}
			fmt.Printf(">>>>\n%#v\n", f)
			p.errors.RemoveMultiples()
			parseErr := p.errors.Err()

			var ebuf bytes.Buffer
			goscanner.PrintError(&ebuf, parseErr)

			var buf bytes.Buffer
			pp := printer{w: &buf, withPos: true, withComments: true}
			if err := pp.Print(f, p.file); err != nil {
				t.Fatal(err)
			}
			t.Logf("\n%s\n", buf.String())

			wantFile := filepath.Join("testdata", fi.Name()+".want")
			errFile := filepath.Join("testdata", fi.Name()+".err")
			if *testUpdateParserTests {
				if err := ioutil.WriteFile(wantFile, buf.Bytes(), 0666); err != nil {
					t.Fatal(err)
				}

				if err := ioutil.WriteFile(errFile, ebuf.Bytes(), 0666); err != nil {
					t.Fatal(err)
				}
				return
			}

			// validate AST output
			want, err := ioutil.ReadFile(wantFile)
			if err != nil && !os.IsNotExist(err) {
				t.Fatal(err)
			}
			t.Logf("got:\n%s\n", buf.String())
			t.Logf("want:\n%s\n", string(want))
			if patch := diff.Diff(buf.String(), string(want)); patch != "" {
				t.Errorf("diff:\n%s\n", patch)
			}

			// validate errors output
			ewant, err := ioutil.ReadFile(errFile)
			if err != nil && !os.IsNotExist(err) {
				t.Fatal(err)
			}
			t.Logf("got error(s):\n%s\n", ebuf.String())
			t.Logf("want error(s):\n%s\n", string(ewant))
			if patch := diff.Diff(ebuf.String(), string(ewant)); patch != "" {
				t.Errorf("diff error(s):\n%s\n", patch)
			}
		})
	}
}

M pkg/compiler/printer.go => pkg/compiler/printer.go +10 -3
@@ 89,7 89,14 @@ func (p *printer) Visit(n node) visitor {
	case *block:
		p.printMsg("block", true)
	case *varDef:
		p.printMsg("var", true)
		lbl := n.kw.String()
		if n.colon.IsValid() {
			lbl += ":"
		}
		if n.assign.IsValid() {
			lbl += "="
		}
		p.printMsg(lbl, true)
	case *returnStmt:
		p.printMsg("return", true)
	case *binaryExpr:


@@ 99,9 106,9 @@ func (p *printer) Visit(n node) visitor {
	case *parenExpr:
		p.printMsg("paren", true)
	case *basicLit:
		p.printMsg(fmt.Sprintf("%s [%q]", n.literal, n.value), true)
		p.printMsg(fmt.Sprintf("%s [%s]", n.literal, n.value), true)
	case *ident:
		p.printMsg(fmt.Sprintf("ident [%q]", n.name), true)
		p.printMsg(fmt.Sprintf("ident [%s]", n.name), true)
	case *badStmt:
		p.printMsg("bad stmt", true)
	case *badExpr:

M pkg/compiler/printer_test.go => pkg/compiler/printer_test.go +52 -50
@@ 6,6 6,8 @@ import (
	gotoken "go/token"
	"strings"
	"testing"

	"github.com/kylelemons/godebug/diff"
)

func TestPrinter(t *testing.T) {


@@ 109,94 111,94 @@ func TestPrinter(t *testing.T) {

	wantNoPos := `
file
    var
      ident ["a"]
      ident ["int"]
      int ["1"]
    var:=
      ident [a]
      ident [int]
      int [1]
    fn
      ident ["add"]
      ident [add]
      sig
        param
          ident ["x"]
          ident ["int"]
          ident [x]
          ident [int]
        param
          ident ["y"]
          ident ["int"]
        ident ["int"]
          ident [y]
          ident [int]
        ident [int]
      block
        return
          binary [+]
            ident ["x"]
            ident ["y"]
            ident [x]
            ident [y]
`
	wantComments := `
file
  comments
    comment [#abc]
    comment [#def]
  var
    ident ["a"]
    ident ["int"]
    int ["1"]
  var:=
    ident [a]
    ident [int]
    int [1]
  fn
    ident ["add"]
    ident [add]
    sig
      param
        ident ["x"]
        ident ["int"]
        ident [x]
        ident [int]
      param
        ident ["y"]
        ident ["int"]
      ident ["int"]
        ident [y]
        ident [int]
      ident [int]
    block
      return
        binary [+]
          ident ["x"]
          ident ["y"]
          ident [x]
          ident [y]
`
	wantShort := `
file [0:69]
    var [8:22]
      ident ["a"] [12:13]
      ident ["int"] [15:18]
      int ["1"] [21:22]
    var:= [8:22]
      ident [a] [12:13]
      ident [int] [15:18]
      int [1] [21:22]
    fn [23:69]
      ident ["add"] [26:29]
      ident [add] [26:29]
      sig [30:51]
        param [31:38]
          ident ["x"] [31:32]
          ident ["int"] [34:37]
          ident [x] [31:32]
          ident [int] [34:37]
        param [39:45]
          ident ["y"] [39:40]
          ident ["int"] [42:45]
        ident ["int"] [48:51]
          ident [y] [39:40]
          ident [int] [42:45]
        ident [int] [48:51]
      block [52:69]
        return [56:67]
          binary [+] [64:67]
            ident ["x"] [64:65]
            ident ["y"] [66:67]
            ident [x] [64:65]
            ident [y] [66:67]
`
	wantLong := `
file [test:1:1::1:70]
    var [test:1:9::1:23]
      ident ["a"] [test:1:13::1:14]
      ident ["int"] [test:1:16::1:19]
      int ["1"] [test:1:22::1:23]
    var:= [test:1:9::1:23]
      ident [a] [test:1:13::1:14]
      ident [int] [test:1:16::1:19]
      int [1] [test:1:22::1:23]
    fn [test:1:24::1:70]
      ident ["add"] [test:1:27::1:30]
      ident [add] [test:1:27::1:30]
      sig [test:1:31::1:52]
        param [test:1:32::1:39]
          ident ["x"] [test:1:32::1:33]
          ident ["int"] [test:1:35::1:38]
          ident [x] [test:1:32::1:33]
          ident [int] [test:1:35::1:38]
        param [test:1:40::1:46]
          ident ["y"] [test:1:40::1:41]
          ident ["int"] [test:1:43::1:46]
        ident ["int"] [test:1:49::1:52]
          ident [y] [test:1:40::1:41]
          ident [int] [test:1:43::1:46]
        ident [int] [test:1:49::1:52]
      block [test:1:53::1:70]
        return [test:1:57::1:68]
          binary [+] [test:1:65::1:68]
            ident ["x"] [test:1:65::1:66]
            ident ["y"] [test:1:67::1:68]
            ident [x] [test:1:65::1:66]
            ident [y] [test:1:67::1:68]
`

	cases := []struct {


@@ 225,8 227,8 @@ file [test:1:1::1:70]

			want := strings.TrimSpace(c.want)
			got := strings.TrimSpace(buf.String())
			if want != got {
				t.Fatalf("want:\n%s\ngot:\n%s\n", want, got)
			if patch := diff.Diff(got, want); patch != "" {
				t.Fatalf("diff:\n%s\n", patch)
			}
		})
	}

A pkg/compiler/testdata/comment.snow => pkg/compiler/testdata/comment.snow +1 -0
@@ 0,0 1,1 @@
# hello

A pkg/compiler/testdata/comment.snow.err => pkg/compiler/testdata/comment.snow.err +0 -0
A pkg/compiler/testdata/comment.snow.want => pkg/compiler/testdata/comment.snow.want +3 -0
@@ 0,0 1,3 @@
file [0:7]
  comments [0:7]
    comment [# hello] [0:7]

A pkg/compiler/testdata/comments.snow => pkg/compiler/testdata/comments.snow +10 -0
@@ 0,0 1,10 @@
# group a.1
# group a.2
  # group a.3

# group a.4

$

# group b.1
# group b.2

A pkg/compiler/testdata/comments.snow.err => pkg/compiler/testdata/comments.snow.err +1 -0
@@ 0,0 1,1 @@
comments.snow:7:1: expected statement, found 'illegal'

A pkg/compiler/testdata/comments.snow.want => pkg/compiler/testdata/comments.snow.want +10 -0
@@ 0,0 1,10 @@
file [0:79]
  comments [0:50]
    comment [# group a.1] [0:11]
    comment [# group a.2] [12:23]
    comment [# group a.3] [26:37]
    comment [# group a.4] [39:50]
  comments [55:78]
    comment [# group b.1] [55:66]
    comment [# group b.2] [67:78]
  bad stmt [52:79]

A pkg/compiler/testdata/empty.snow.err => pkg/compiler/testdata/empty.snow.err +0 -0
A pkg/compiler/testdata/empty.snow.want => pkg/compiler/testdata/empty.snow.want +1 -0
@@ 0,0 1,1 @@
file [-:-]

A pkg/compiler/testdata/let.snow => pkg/compiler/testdata/let.snow +1 -0
@@ 0,0 1,1 @@
let x: int

A pkg/compiler/testdata/let.snow.err => pkg/compiler/testdata/let.snow.err +0 -0
A pkg/compiler/testdata/let.snow.want => pkg/compiler/testdata/let.snow.want +4 -0
@@ 0,0 1,4 @@
file [0:10]
  let: [0:10]
    ident [x] [4:5]
    ident [int] [7:10]

A pkg/compiler/testdata/let_full.snow => pkg/compiler/testdata/let_full.snow +2 -0
@@ 0,0 1,2 @@
let x: string = "abc"


A pkg/compiler/testdata/let_full.snow.err => pkg/compiler/testdata/let_full.snow.err +0 -0
A pkg/compiler/testdata/let_full.snow.want => pkg/compiler/testdata/let_full.snow.want +5 -0
@@ 0,0 1,5 @@
file [0:21]
  let:= [0:21]
    ident [x] [4:5]
    ident [string] [7:13]
    string ["abc"] [16:21]

A pkg/compiler/testdata/let_infer.snow => pkg/compiler/testdata/let_infer.snow +1 -0
@@ 0,0 1,1 @@
let x = "a"

A pkg/compiler/testdata/let_infer.snow.err => pkg/compiler/testdata/let_infer.snow.err +0 -0
A pkg/compiler/testdata/let_infer.snow.want => pkg/compiler/testdata/let_infer.snow.want +4 -0
@@ 0,0 1,4 @@
file [0:11]
  let= [0:11]
    ident [x] [4:5]
    string ["a"] [8:11]

A pkg/compiler/testdata/var.snow => pkg/compiler/testdata/var.snow +1 -0
@@ 0,0 1,1 @@
var x: int

A pkg/compiler/testdata/var.snow.err => pkg/compiler/testdata/var.snow.err +0 -0
A pkg/compiler/testdata/var.snow.want => pkg/compiler/testdata/var.snow.want +4 -0
@@ 0,0 1,4 @@
file [0:10]
  var: [0:10]
    ident [x] [4:5]
    ident [int] [7:10]

A pkg/compiler/testdata/var_full.snow => pkg/compiler/testdata/var_full.snow +2 -0
@@ 0,0 1,2 @@
var x: int = 123


A pkg/compiler/testdata/var_full.snow.err => pkg/compiler/testdata/var_full.snow.err +0 -0
A pkg/compiler/testdata/var_full.snow.want => pkg/compiler/testdata/var_full.snow.want +5 -0
@@ 0,0 1,5 @@
file [0:16]
  var:= [0:16]
    ident [x] [4:5]
    ident [int] [7:10]
    int [123] [13:16]

A pkg/compiler/testdata/var_infer.snow => pkg/compiler/testdata/var_infer.snow +1 -0
@@ 0,0 1,1 @@
var x = 10

A pkg/compiler/testdata/var_infer.snow.err => pkg/compiler/testdata/var_infer.snow.err +0 -0
A pkg/compiler/testdata/var_infer.snow.want => pkg/compiler/testdata/var_infer.snow.want +4 -0
@@ 0,0 1,4 @@
file [0:10]
  var= [0:10]
    ident [x] [4:5]
    int [10] [8:10]