Skip to content

Commit

Permalink
Merge pull request #148 from NeowayLabs/add-return-fn
Browse files Browse the repository at this point in the history
Add support for fncall in return
  • Loading branch information
i4ki authored Nov 21, 2016
2 parents 93b28d5 + 49af47e commit 6728666
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 89 deletions.
14 changes: 4 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ matrix:
- os: osx

language: go
sudo: required

services:
- docker
sudo: false

go:
- tip
- 1.7
- 1.6
- 1.5
install:
Expand All @@ -23,13 +22,8 @@ script:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
- make test
# - goveralls -coverprofile=coverage.txt -service=travis-ci
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install go ; fi
- sudo pip install codecov
after_success:
codecov
- bash <(curl -s https://codecov.io/bash)
notifications:
webhooks:
urls:
Expand Down
2 changes: 1 addition & 1 deletion cmd/nash/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
all: build install

VERSION=$(shell git rev-parse --abbrev-ref HEAD)
BUILDARGS = -ldflags "-linkmode external -extldflags -static -X main.VersionString=$(VERSION)" -v
BUILDARGS = -installsuffix netgo -ldflags "-linkmode external -extldflags -static -X main.VersionString=$(VERSION)" -v

build:
GO15VENDOREXPERIMENT=1 go build $(BUILDARGS)
Expand Down
122 changes: 47 additions & 75 deletions internal/sh/shell_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1175,35 +1175,22 @@ func TestExecuteUDPRedirection(t *testing.T) {
}

func TestExecuteReturn(t *testing.T) {
shell, err := NewShell()

if err != nil {
t.Error(err)
return
}

shell.SetNashdPath(nashdPath)

err = shell.Exec("test return fail", "return")

if err == nil {
t.Errorf("Must fail. Return is only valid inside function")
return
}

err = shell.Exec("test return", `fn test() { return }
test()`)

if err != nil {
t.Error(err)
return
}

var out bytes.Buffer

shell.SetStdout(&out)

err = shell.Exec("test return", `fn test() {
for _, test := range []execTest{
{
"return invalid",
`return`,
"", "",
"<interactive>:1:0: Unexpected return outside of function declaration.",
},
{
"test simple return",
`fn test() { return }
test()`,
"", "", "",
},
{
"return must finish func evaluation",
`fn test() {
if "1" == "1" {
return "1"
}
Expand All @@ -1212,23 +1199,12 @@ test()`)
}
res <= test()
echo -n $res`)

if err != nil {
t.Error(err)
return
}

got := string(out.Bytes())

if got != "1" {
t.Errorf("Expected '1' but got '%s'", got)
return
}

out.Reset()

err = shell.Exec("ret from for", `fn test() {
echo -n $res`,
"1", "", "",
},
{
"ret from for",
`fn test() {
values = (0 1 2 3 4 5 6 7 8 9)
for i in $values {
Expand All @@ -1240,23 +1216,12 @@ echo -n $res`)
return "0"
}
a <= test()
echo -n $a`)

if err != nil {
t.Error(err)
return
}

got = string(out.Bytes())

if "5" != got {
t.Errorf("Expected '5' but got '%s'", got)
return
}

out.Reset()

err = shell.Exec("inf loop ret", `fn test() {
echo -n $a`,
"5", "", "",
},
{
"inf loop ret",
`fn test() {
for {
if "1" == "1" {
return "1"
Expand All @@ -1267,18 +1232,25 @@ echo -n $a`)
return "bleh"
}
a <= test()
echo -n $a`)

if err != nil {
t.Error(err)
return
}

got = string(out.Bytes())

if got != "1" {
t.Errorf("Expected '1' but got '%s'", got)
return
echo -n $a`,
"1", "", "",
},
{
"test returning funcall",
`fn a() { return "1" }
fn b() { return a() }
c <= b()
echo -n $c`,
"1", "", "",
},
} {
testExec(t,
test.desc,
test.execStr,
test.expectedStdout,
test.expectedStderr,
test.expectedErr,
)
}
}

Expand Down
26 changes: 24 additions & 2 deletions parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,13 +1078,15 @@ func (p *Parser) parseReturn(retIt scanner.Token) (ast.Node, error) {
// return $v
// return "<some>"
// return ( ... values ... )
// return <fn name>()
if valueIt.Type() != token.Semicolon &&
valueIt.Type() != token.RBrace &&
valueIt.Type() != token.Variable &&
valueIt.Type() != token.String &&
valueIt.Type() != token.LParen {
valueIt.Type() != token.LParen &&
valueIt.Type() != token.Ident {
return nil, newParserError(valueIt, p.name,
"Expected ';', STRING, VARIABLE or LPAREN, but found %v",
"Expected ';', STRING, VARIABLE, FUNCALL or LPAREN, but found %v",
valueIt)
}

Expand Down Expand Up @@ -1128,6 +1130,26 @@ func (p *Parser) parseReturn(retIt scanner.Token) (ast.Node, error) {
return ret, nil
}

if valueIt.Type() == token.Ident {
p.next()
next := p.peek()

if next.Type() != token.LParen {
return nil, newParserError(valueIt, p.name,
"Expected FUNCALL, STRING, VARIABLE or LPAREN, but found %v %v",
valueIt, next)
}

arg, err := p.parseFnInv(valueIt, true)

if err != nil {
return nil, err
}

ret.SetReturn(arg)
return ret, nil
}

arg, err := p.getArgument(false, true)

if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,20 @@ func TestParseReturn(t *testing.T) {
expected.Root = ln

parserTestTable("return", `return "value"`, expected, t, true)

expected = ast.NewTree("return funcall")
ln = ast.NewBlockNode(token.NewFileInfo(1, 0))

ret = ast.NewReturnNode(token.NewFileInfo(1, 0))

aFn := ast.NewFnInvNode(token.NewFileInfo(1, 7), "a")

ret.SetReturn(aFn)

ln.Push(ret)
expected.Root = ln

parserTestTable("return", `return a()`, expected, t, true)
}

func TestParseIfInvalid(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion spec.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fnArgs = { fnArg [ "," ] } .
fnArg = identifier .

/* return declaration */
returnDecl = "return" [ ( variable | string_lit | list ) ] .
returnDecl = "return" [ ( variable | string_lit | list | fnInv ) ] .

/* Function invocation */
fnInv = ( variable | identifier ) "(" fnArgValues ")" .
Expand Down

0 comments on commit 6728666

Please sign in to comment.