Skip to content

Commit 6728666

Browse files
authored
Merge pull request #148 from NeowayLabs/add-return-fn
Add support for fncall in return
2 parents 93b28d5 + 49af47e commit 6728666

File tree

6 files changed

+91
-89
lines changed

6 files changed

+91
-89
lines changed

.travis.yml

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ matrix:
77
- os: osx
88

99
language: go
10-
sudo: required
11-
12-
services:
13-
- docker
10+
sudo: false
1411

1512
go:
13+
- tip
14+
- 1.7
1615
- 1.6
1716
- 1.5
1817
install:
@@ -23,13 +22,8 @@ script:
2322
- go get github.com/mattn/goveralls
2423
- go get golang.org/x/tools/cmd/cover
2524
- make test
26-
# - goveralls -coverprofile=coverage.txt -service=travis-ci
27-
before_install:
28-
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
29-
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install go ; fi
30-
- sudo pip install codecov
3125
after_success:
32-
codecov
26+
- bash <(curl -s https://codecov.io/bash)
3327
notifications:
3428
webhooks:
3529
urls:

cmd/nash/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
all: build install
22

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

66
build:
77
GO15VENDOREXPERIMENT=1 go build $(BUILDARGS)

internal/sh/shell_test.go

+47-75
Original file line numberDiff line numberDiff line change
@@ -1175,35 +1175,22 @@ func TestExecuteUDPRedirection(t *testing.T) {
11751175
}
11761176

11771177
func TestExecuteReturn(t *testing.T) {
1178-
shell, err := NewShell()
1179-
1180-
if err != nil {
1181-
t.Error(err)
1182-
return
1183-
}
1184-
1185-
shell.SetNashdPath(nashdPath)
1186-
1187-
err = shell.Exec("test return fail", "return")
1188-
1189-
if err == nil {
1190-
t.Errorf("Must fail. Return is only valid inside function")
1191-
return
1192-
}
1193-
1194-
err = shell.Exec("test return", `fn test() { return }
1195-
test()`)
1196-
1197-
if err != nil {
1198-
t.Error(err)
1199-
return
1200-
}
1201-
1202-
var out bytes.Buffer
1203-
1204-
shell.SetStdout(&out)
1205-
1206-
err = shell.Exec("test return", `fn test() {
1178+
for _, test := range []execTest{
1179+
{
1180+
"return invalid",
1181+
`return`,
1182+
"", "",
1183+
"<interactive>:1:0: Unexpected return outside of function declaration.",
1184+
},
1185+
{
1186+
"test simple return",
1187+
`fn test() { return }
1188+
test()`,
1189+
"", "", "",
1190+
},
1191+
{
1192+
"return must finish func evaluation",
1193+
`fn test() {
12071194
if "1" == "1" {
12081195
return "1"
12091196
}
@@ -1212,23 +1199,12 @@ test()`)
12121199
}
12131200
12141201
res <= test()
1215-
echo -n $res`)
1216-
1217-
if err != nil {
1218-
t.Error(err)
1219-
return
1220-
}
1221-
1222-
got := string(out.Bytes())
1223-
1224-
if got != "1" {
1225-
t.Errorf("Expected '1' but got '%s'", got)
1226-
return
1227-
}
1228-
1229-
out.Reset()
1230-
1231-
err = shell.Exec("ret from for", `fn test() {
1202+
echo -n $res`,
1203+
"1", "", "",
1204+
},
1205+
{
1206+
"ret from for",
1207+
`fn test() {
12321208
values = (0 1 2 3 4 5 6 7 8 9)
12331209
12341210
for i in $values {
@@ -1240,23 +1216,12 @@ echo -n $res`)
12401216
return "0"
12411217
}
12421218
a <= test()
1243-
echo -n $a`)
1244-
1245-
if err != nil {
1246-
t.Error(err)
1247-
return
1248-
}
1249-
1250-
got = string(out.Bytes())
1251-
1252-
if "5" != got {
1253-
t.Errorf("Expected '5' but got '%s'", got)
1254-
return
1255-
}
1256-
1257-
out.Reset()
1258-
1259-
err = shell.Exec("inf loop ret", `fn test() {
1219+
echo -n $a`,
1220+
"5", "", "",
1221+
},
1222+
{
1223+
"inf loop ret",
1224+
`fn test() {
12601225
for {
12611226
if "1" == "1" {
12621227
return "1"
@@ -1267,18 +1232,25 @@ echo -n $a`)
12671232
return "bleh"
12681233
}
12691234
a <= test()
1270-
echo -n $a`)
1271-
1272-
if err != nil {
1273-
t.Error(err)
1274-
return
1275-
}
1276-
1277-
got = string(out.Bytes())
1278-
1279-
if got != "1" {
1280-
t.Errorf("Expected '1' but got '%s'", got)
1281-
return
1235+
echo -n $a`,
1236+
"1", "", "",
1237+
},
1238+
{
1239+
"test returning funcall",
1240+
`fn a() { return "1" }
1241+
fn b() { return a() }
1242+
c <= b()
1243+
echo -n $c`,
1244+
"1", "", "",
1245+
},
1246+
} {
1247+
testExec(t,
1248+
test.desc,
1249+
test.execStr,
1250+
test.expectedStdout,
1251+
test.expectedStderr,
1252+
test.expectedErr,
1253+
)
12821254
}
12831255
}
12841256

parser/parse.go

+24-2
Original file line numberDiff line numberDiff line change
@@ -1078,13 +1078,15 @@ func (p *Parser) parseReturn(retIt scanner.Token) (ast.Node, error) {
10781078
// return $v
10791079
// return "<some>"
10801080
// return ( ... values ... )
1081+
// return <fn name>()
10811082
if valueIt.Type() != token.Semicolon &&
10821083
valueIt.Type() != token.RBrace &&
10831084
valueIt.Type() != token.Variable &&
10841085
valueIt.Type() != token.String &&
1085-
valueIt.Type() != token.LParen {
1086+
valueIt.Type() != token.LParen &&
1087+
valueIt.Type() != token.Ident {
10861088
return nil, newParserError(valueIt, p.name,
1087-
"Expected ';', STRING, VARIABLE or LPAREN, but found %v",
1089+
"Expected ';', STRING, VARIABLE, FUNCALL or LPAREN, but found %v",
10881090
valueIt)
10891091
}
10901092

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

1133+
if valueIt.Type() == token.Ident {
1134+
p.next()
1135+
next := p.peek()
1136+
1137+
if next.Type() != token.LParen {
1138+
return nil, newParserError(valueIt, p.name,
1139+
"Expected FUNCALL, STRING, VARIABLE or LPAREN, but found %v %v",
1140+
valueIt, next)
1141+
}
1142+
1143+
arg, err := p.parseFnInv(valueIt, true)
1144+
1145+
if err != nil {
1146+
return nil, err
1147+
}
1148+
1149+
ret.SetReturn(arg)
1150+
return ret, nil
1151+
}
1152+
11311153
arg, err := p.getArgument(false, true)
11321154

11331155
if err != nil {

parser/parse_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,20 @@ func TestParseReturn(t *testing.T) {
11691169
expected.Root = ln
11701170

11711171
parserTestTable("return", `return "value"`, expected, t, true)
1172+
1173+
expected = ast.NewTree("return funcall")
1174+
ln = ast.NewBlockNode(token.NewFileInfo(1, 0))
1175+
1176+
ret = ast.NewReturnNode(token.NewFileInfo(1, 0))
1177+
1178+
aFn := ast.NewFnInvNode(token.NewFileInfo(1, 7), "a")
1179+
1180+
ret.SetReturn(aFn)
1181+
1182+
ln.Push(ret)
1183+
expected.Root = ln
1184+
1185+
parserTestTable("return", `return a()`, expected, t, true)
11721186
}
11731187

11741188
func TestParseIfInvalid(t *testing.T) {

spec.ebnf

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fnArgs = { fnArg [ "," ] } .
5151
fnArg = identifier .
5252

5353
/* return declaration */
54-
returnDecl = "return" [ ( variable | string_lit | list ) ] .
54+
returnDecl = "return" [ ( variable | string_lit | list | fnInv ) ] .
5555

5656
/* Function invocation */
5757
fnInv = ( variable | identifier ) "(" fnArgValues ")" .

0 commit comments

Comments
 (0)