openllb / hlb

A developer-first language to build and test any software efficiently
https://openllb.github.io/hlb/
Apache License 2.0
108 stars 12 forks source link

hlb panic in `ast.(*Type).Spanf` #349

Open coryb opened 1 year ago

coryb commented 1 year ago

build.hlb file:

fs _first() {
    image "busybox"
    run "echo first" with option {
        mount scratch localCwd as first
    }
}

fs _second() {
    _first
    run "echo second" option {
        mount first localCwd as second
    }
}

Note run "echo second" option should be written as run "echo second" with option but I would not expect this panic from the source.

go run ./cmd/hlb run --log-output plain -t second causes:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x105196f30]

goroutine 1 [running]:
github.com/openllb/hlb/parser/ast.(*Type).Spanf(0x105588469?, 0x28?, {0x1055a0d9b?, 0x0?}, {0x0?, 0x0?, 0x0?})
    <autogenerated>:1 +0x30
github.com/openllb/hlb/errdefs.WithNoBindClosure({0x1059cf530, 0x14000493da0}, {0x1059d0268, 0x0})
    /src/errdefs/errors.go:171 +0xb0
github.com/openllb/hlb/checker.(*checker).checkBinds.func3(0x0?, 0x0?)
    /src/checker/checker.go:193 +0x44
reflect.Value.call({0x1057c5400?, 0x14000440bf0?, 0x140005647f8?}, {0x105556741, 0x4}, {0x140003f4ba0, 0x2, 0x105187364?})
    /usr/local/go/src/reflect/value.go:586 +0x838
reflect.Value.Call({0x1057c5400?, 0x14000440bf0?, 0x2?}, {0x140003f4ba0?, 0x140001f7810?, 0x1059cf7b8?})
    /usr/local/go/src/reflect/value.go:370 +0x90
github.com/openllb/hlb/parser/ast.(*matcher).Visit(0x140001f7810, {0x1059bf5a0, 0x1400000c438}, {0x1059cf608?, 0x1400014d000?})
    /src/parser/ast/match.go:141 +0x264
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf608?, 0x1400014d000?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:47 +0x154
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf800?, 0x1400008a630?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:152 +0x814
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059d0148?, 0x1400051b3b0?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:137 +0x760
github.com/openllb/hlb/parser/ast.(*walker).walkStmtList(0x140001f7810?, {0x14000440610, 0x2, 0x1059cf728?}, {0x1059bf580, 0x140001f7810})
    /src/parser/ast/walk.go:317 +0x50
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf728?, 0x14000432ea0?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:133 +0x6c8
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cfc80?, 0x14000264900?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:215 +0xc08
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf9f8?, 0x1400051a700?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:204 +0xb98
github.com/openllb/hlb/parser/ast.(*walker).walkExprList(0x1400000c438?, {0x14000440650, 0x2, 0x1059bf580?}, {0x1059bf580, 0x140001f7810})
    /src/parser/ast/walk.go:305 +0x50
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf800?, 0x1400008a790?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:147 +0x7cc
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059d0148?, 0x1400003b260?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:137 +0x760
github.com/openllb/hlb/parser/ast.(*walker).walkStmtList(0x140001f7810?, {0x140003f6dc0, 0x3, 0x1059cf728?}, {0x1059bf580, 0x140001f7810})
    /src/parser/ast/walk.go:317 +0x50
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf728?, 0x14000433440?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:133 +0x6c8
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cfc38?, 0x1400016b650?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:87 +0x3d0
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cf8d8?, 0x140003ce780?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:64 +0x244
github.com/openllb/hlb/parser/ast.(*walker).walkDeclList(0x140001f7810?, {0x1400051f680, 0x9, 0x1059cff98?}, {0x1059bf580, 0x140001f7810})
    /src/parser/ast/walk.go:287 +0x50
github.com/openllb/hlb/parser/ast.(*walker).walk(0x1400000c438, {0x1059cff98?, 0x140003ee8c0?}, {0x1059bf580?, 0x140001f7810?})
    /src/parser/ast/walk.go:56 +0x1c8
github.com/openllb/hlb/parser/ast.Walk(...)
    /src/parser/ast/walk.go:30
github.com/openllb/hlb/parser/ast.Match({0x1059cff98, 0x140003ee8c0}, {0x0?, 0x60?}, {0x14000565328, 0x3, 0x1057e3080?})
    /src/parser/ast/match.go:87 +0x448
github.com/openllb/hlb/checker.(*checker).checkBinds(0x140003f47e0, 0x140003ee8c0)
    /src/checker/checker.go:168 +0x11c
github.com/openllb/hlb/checker.(*checker).SemanticPass(0x140003f47e0, 0x140003ee8c0)
    /src/checker/checker.go:146 +0x2d0
github.com/openllb/hlb/checker.SemanticPass(...)
    /src/checker/checker.go:21
github.com/openllb/hlb.Compile({0x1059cc780, 0x140000ae140}, 0x140006977a0, {0x1059c1100, 0x14000126010}, 0x16b2c3452?, {0x14000440a60, 0x1, 0x1})
    /src/hlb.go:35 +0x84
github.com/openllb/hlb/cmd/hlb/command.Run({_, _}, _, {_, _}, {0x0, 0x0, 0x0, {0x14000697430, 0x1, ...}, ...})
    /src/cmd/hlb/command/run.go:291 +0x136c
github.com/openllb/hlb/cmd/hlb/command.glob..func7(0x1400021a540?)
    /src/cmd/hlb/command/run.go:87 +0x288
github.com/urfave/cli/v2.(*Command).Run(0x106176ac0, 0x140002ebe40)
    /go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/command.go:163 +0x4c4
github.com/urfave/cli/v2.(*App).RunContext(0x14000683d40, {0x1059cc7b8?, 0x1400012c008}, {0x14000132000, 0x7, 0x7})
    /go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/app.go:313 +0x810
github.com/urfave/cli/v2.(*App).Run(0x1400010c000?, {0x14000132000?, 0x14000072768?, 0x104b73cdc?})
    /go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/app.go:224 +0x40
main.main()
    /src/cmd/hlb/main.go:12 +0x38
exit status 2
hinshun commented 1 year ago

It's parsing the option block after echo second as a func lit. I think this diff will fix it:

diff --git a/checker/checker.go b/checker/checker.go
index 54425fb..63c900b 100644
--- a/checker/checker.go
+++ b/checker/checker.go
@@ -114,9 +114,7 @@ func (c *checker) SemanticPass(mod *ast.Module) error {
        },
        // Function literals propagate its return type to its BlockStmt.
        func(lit *ast.FuncLit) {
-           if lit.Type.Kind != ast.Option {
-               lit.Body.Type = lit.Type
-           }
+           lit.Body.Type = lit.Type
        },
        // ImportDecl's BlockStmts have module-level scope.
        func(_ *ast.ImportDecl, lit *ast.FuncLit) {
coryb commented 1 year ago

Cool, yeah, that is producing a checker error now

error: cannot bind, no closure in option blocks
parse.hlb:11:24:
   │
10 │    run "echo second" option {
   │                      ------
   │                      option blocks have no closures outside of "with option {...}"
11 │        mount first localCwd as second
   │                             ^^
   │                             no closure for binding