~mna/snow unlisted

2d36cd3d27f62d96c885e2a7bd5da47564c339b0 — Martin Angers 1 year, 1 month ago 2e1af6f
pkg/compiler: add return stmt, identify missing semis and expr stmt
M go.mod => go.mod +1 -0
@@ 3,6 3,7 @@ module git.sr.ht/~mna/snow
go 1.13

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

M go.sum => go.sum +5 -0
@@ 1,6 1,11 @@
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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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=

M pkg/compiler/parser.go => pkg/compiler/parser.go +18 -3
@@ 100,7 100,7 @@ func (p *parser) parseFile() *file {

	var stmts []stmt
	for p.tok != EOF {
		stmts = append(stmts, p.parseStmt())
		stmts = append(stmts, p.parseStmt(true))
	}

	return &file{


@@ 109,7 109,14 @@ func (p *parser) parseFile() *file {
	}
}

func (p *parser) parseStmt() stmt {
func (p *parser) parseStmt(topLevel bool) stmt {
	if !topLevel {
		switch p.tok {
		case Return:
			return p.parseReturnStmt()
		}
	}

	switch p.tok {
	case Let, Var:
		return p.parseVarDef()


@@ 123,6 130,14 @@ func (p *parser) parseStmt() stmt {
	}
}

func (p *parser) parseReturnStmt() *returnStmt {
	rs := &returnStmt{
		ret: p.expect(Return),
	}
	// TODO: need auto-semicolons here, can't know if there's an expr after
	return rs
}

func (p *parser) parseVarDef() *varDef {
	vd := &varDef{
		kw:    p.tok,


@@ 267,7 282,7 @@ func (p *parser) parseBlock() *block {
func (p *parser) parseStmtList() []stmt {
	var list []stmt
	for p.tok != Rbrace && p.tok != EOF {
		list = append(list, p.parseStmt())
		list = append(list, p.parseStmt(false))
	}
	return list
}

M pkg/compiler/parser_test.go => pkg/compiler/parser_test.go +1 -0
@@ 43,6 43,7 @@ func TestParser(t *testing.T) {
			f := p.parseFile()
			p.errors.RemoveMultiples()
			parseErr := p.errors.Err()
			//pretty.Print(f)

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

M pkg/compiler/scanner.go => pkg/compiler/scanner.go +1 -0
@@ 161,6 161,7 @@ func (s *scanner) ident() string {
	for isLetter(s.cur) || isDigit(s.cur) {
		s.next()
	}
	// TODO: allow single "!" or "?" at the end
	return string(s.src[off:s.off])
}


A pkg/compiler/testdata/fn.snow => pkg/compiler/testdata/fn.snow +1 -0
@@ 0,0 1,1 @@
fn empty() { }

A pkg/compiler/testdata/fn.snow.err => pkg/compiler/testdata/fn.snow.err +0 -0
A pkg/compiler/testdata/fn.snow.want => pkg/compiler/testdata/fn.snow.want +5 -0
@@ 0,0 1,5 @@
file [0:14]
  fn [0:14]
    ident [empty] [3:8]
    sig [8:10]
    block [11:14]

A pkg/compiler/testdata/fn_add.snow.notyet => pkg/compiler/testdata/fn_add.snow.notyet +3 -0
@@ 0,0 1,3 @@
fn add(x: int, y: int) -> int {
  return x + y
}

A pkg/compiler/testdata/fn_naked_return.snow.notyet => pkg/compiler/testdata/fn_naked_return.snow.notyet +4 -0
@@ 0,0 1,4 @@
fn print(x: int, y: string) {
  x + y
  return
}

M pkg/grammar/grammar.ebnf => pkg/grammar/grammar.ebnf +1 -0
@@ 22,6 22,7 @@ ParamDef = ident ":" ident .
FuncTrailer = "->" ident .
Block = "{" { Stmt } "}" .

// TODO: expression statement
Stmt = VarDef | ReturnStmt .
ReturnStmt = "return" [ Expr ] .