Skip to content

Commit 2bb1487

Browse files
committed
Generate CallName() and MroFileName() methods.
On Args objects generated for callables. This is useful for programs generating .mro files to serve as entry points for running a pipeline, which will generally need look something like @include "pipeline.mro" call PIPELINE( ..., ) These methods allow such a call to be generated by ast_builder.MakeCallAst, without any additional arguments. Add bazel rules for generating code with mro2go. This is a little more complex than is feasible with a genrule because we need to pick up transitive mro sources and set MROPATH properly. Update the generated code comment to use the canonical path to the mro file, to ensure consistency between different ways of running the tool.
1 parent 79ead58 commit 2bb1487

20 files changed

+372
-7
lines changed

cmd/mro2go/BUILD.bazel

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ go_test(
2929
"split_test.go",
3030
],
3131
data = [
32-
"split_test.go",
3332
"split_pipeline_test.go",
33+
"split_test.go",
3434
"struct_pipeline_test.go",
3535
"testdata/pipeline_stages.mro",
3636
"testdata/struct_pipeline.mro",

cmd/mro2go/codegen_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// Copyright (c) 2020 10X Genomics, Inc. All rights reserved.
22

3+
//go:generate -command m2g go run . -p main
4+
//nolint:lll // go:generate's support for splitting a command line is limited.
5+
//go:generate m2g -input-only -pipeline SUM_SQUARE_PIPELINE -o split_pipeline_test.go testdata/pipeline_stages.mro
6+
//go:generate m2g -pipeline OUTER -o struct_pipeline_test.go testdata/struct_pipeline.mro
7+
//go:generate m2g -o split_test.go testdata/pipeline_stages.mro
8+
39
package main
410

511
import (

cmd/mro2go/main.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Given the input pipeline.mro:
8181
)
8282
8383
A user would run
84+
8485
$ mro2go -package populate -o stagestructs.go pipeline.mro
8586
8687
to generate stagestructs.go:
@@ -103,6 +104,16 @@ to generate stagestructs.go:
103104
MinMapqAttachBc int `json:"min_mapq_attach_bc"`
104105
}
105106
107+
// CallName returns the name of this stage as defined in the .mro file.
108+
func (*PopulateInfoFieldsArgs) CallName() string {
109+
return "POPULATE_INFO_FIELDS"
110+
}
111+
112+
// MroFileName returns the name of the .mro file which defines this stage.
113+
func (*PopulateInfoFieldsArgs) MroFileName() string {
114+
return "pipeline.mro"
115+
}
116+
106117
// A structure to encode and decode outs from the POPULATE_INFO_FIELDS stage.
107118
type PopulateInfoFieldsOuts struct {
108119
// vcf.gz file
@@ -221,8 +232,7 @@ func main() {
221232
"Could not get working directory: %v\n",
222233
err)
223234
}
224-
mroPaths := append([]string{cwd},
225-
util.ParseMroPath(os.Getenv("MROPATH"))...)
235+
mroPaths := append(util.ParseMroPath(os.Getenv("MROPATH")), cwd)
226236
var f *os.File
227237
if *stdout {
228238
f = os.Stdout
@@ -364,11 +374,15 @@ func MroToGo(dest io.Writer,
364374
src []byte, mrofile string, stageNames, mroPaths []string,
365375
pkg, outName string, pipeline, onlyIns bool,
366376
seenStructs map[string]struct{}) error {
377+
canonicalPath, _, err := syntax.IncludeFilePath(mrofile, mroPaths)
378+
if err != nil {
379+
return err
380+
}
367381
if ast, err := parseMro(src, mrofile, mroPaths); err != nil {
368382
return err
369383
} else {
370384
return gofmt(dest,
371-
makeCallableGoRaw(ast, pkg, mrofile, stageNames,
385+
makeCallableGoRaw(ast, pkg, canonicalPath, stageNames,
372386
pipeline, onlyIns, seenStructs), outName)
373387
}
374388
}

cmd/mro2go/split_pipeline_test.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/mro2go/split_test.go

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/mro2go/stage_generator.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package main
77
import (
88
"bytes"
99
"fmt"
10+
"strconv"
1011
"strings"
1112
"unicode"
1213

@@ -191,7 +192,28 @@ func writeStageArgs(buffer *bytes.Buffer, lookup *syntax.TypeLookup,
191192
for _, param := range stage.GetInParams().List {
192193
writeParam(buffer, lookup, param)
193194
}
194-
buffer.WriteString("}\n\n")
195+
buffer.WriteString(`}
196+
197+
// CallName returns the name of this `)
198+
buffer.WriteString(stage.Type())
199+
buffer.WriteString(` as defined in the .mro file.
200+
func (*`)
201+
buffer.WriteString(prefix)
202+
buffer.WriteString(`Args) CallName() string {
203+
return `)
204+
buffer.Write(strconv.AppendQuote(make([]byte, 0, 255), stage.GetId()))
205+
buffer.WriteString(`
206+
}
207+
208+
// MroFileName returns the name of the .mro file which defines this `)
209+
buffer.WriteString(stage.Type())
210+
buffer.WriteString(`.
211+
func (*`)
212+
buffer.WriteString(prefix)
213+
buffer.WriteString(`Args) MroFileName() string {
214+
return `)
215+
buffer.Write(strconv.AppendQuote(make([]byte, 0, 255), stage.File().FileName))
216+
buffer.WriteString("\n}\n\n")
195217
}
196218

197219
func writeStageOuts(buffer *bytes.Buffer, lookup *syntax.TypeLookup,

cmd/mro2go/struct_pipeline_test.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

martian/syntax/ast_builder/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go_library(
44
name = "ast_builder",
55
srcs = [
66
"exp.go",
7+
"make_call_mro.go",
78
"struct.go",
89
],
910
importpath = "github.com/martian-lang/martian/martian/syntax/ast_builder",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package ast_builder
2+
3+
import "github.com/martian-lang/martian/martian/syntax"
4+
5+
// An object, compatible with Bindings (that is, either a string-keyed map or
6+
// a struct), which can be used to generate a top-level call.
7+
type CallableArgs interface {
8+
// CallName returns the name of this stage as defined in the .mro file.
9+
CallName() string
10+
// MroFileName returns the name of the .mro file which defines this stage.
11+
MroFileName() string
12+
}
13+
14+
// MakeCallAst generates an ast for a top-level call mro file from an Args
15+
// object as generated by mro2go.
16+
func MakeCallAst(input CallableArgs) *syntax.Ast {
17+
bindings, err := Bindings(input)
18+
if err != nil {
19+
panic(err)
20+
}
21+
return &syntax.Ast{
22+
Includes: []*syntax.Include{{Value: input.MroFileName()}},
23+
Call: &syntax.CallStm{
24+
Id: input.CallName(),
25+
DecId: input.CallName(),
26+
Bindings: bindings,
27+
},
28+
}
29+
}

martian/test/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ go_library(
1111
mro_library(
1212
name = "sum_squares",
1313
srcs = ["sum_squares.mro"],
14+
visibility = [":__subpackages__"],
1415
)
1516

1617
mro_test(

martian/test/pipeline_gen/BUILD.bazel

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
2+
load("//tools:mro2go.bzl", "mro2go_library")
3+
4+
mro2go_library(
5+
name = "pipeline_args",
6+
testonly = True,
7+
srcs = ["//test/split_test_go:pipeline_stages"],
8+
importpath = "github.com/martian-lang/martian/martian/test/pipeline_gen",
9+
pipelines = ["SUM_SQUARE_PIPELINE"],
10+
)
11+
12+
go_library(
13+
name = "pipeline_gen",
14+
testonly = True,
15+
srcs = ["generate_pipeline.go"],
16+
embed = [":pipeline_args"],
17+
deps = [
18+
"//martian/syntax/ast_builder",
19+
],
20+
)
21+
22+
go_test(
23+
name = "pipeline_gen_test",
24+
size = "small",
25+
srcs = ["generate_pipeline_test.go"],
26+
embed = [":pipeline_gen"],
27+
gotags = ["bazel"],
28+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build bazel
2+
// +build bazel
3+
4+
// Package pipeline_gen is used to test the bazel rules for mro2go.
5+
//
6+
// It cannot be compiled without bazel.
7+
package pipeline_gen
8+
9+
import "github.com/martian-lang/martian/martian/syntax/ast_builder"
10+
11+
func GeneratePipeline(values []float64, disableSq bool) string {
12+
return ast_builder.MakeCallAst(&SumSquarePipelineArgs{
13+
Values: values,
14+
DisableSq: disableSq,
15+
}).Format()
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build bazel
2+
// +build bazel
3+
4+
package pipeline_gen
5+
6+
import "testing"
7+
8+
func TestGeneratePipeline(t *testing.T) {
9+
src := GeneratePipeline([]float64{1, 2, 3}, false)
10+
const expected = `@include "pipeline_stages.mro"
11+
12+
call SUM_SQUARE_PIPELINE(
13+
values = [
14+
1,
15+
2,
16+
3,
17+
],
18+
disable_sq = false,
19+
)
20+
`
21+
if src != expected {
22+
t.Error(src, "!=", expected)
23+
}
24+
}

martian/test/sum_squares/BUILD.bazel

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
2+
load("//tools:mro2go.bzl", "mro2go_codegen")
3+
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
24

35
go_library(
46
name = "sum_squares_lib",
@@ -20,3 +22,18 @@ go_binary(
2022
embed = [":sum_squares_lib"],
2123
visibility = ["//visibility:public"],
2224
)
25+
26+
mro2go_codegen(
27+
name = "generate_types",
28+
testonly = True,
29+
srcs = [
30+
"//martian/test:sum_squares",
31+
],
32+
package = "main",
33+
)
34+
35+
diff_test(
36+
name = "generate_types_diff_test",
37+
file1 = "types.go",
38+
file2 = ":generate_types",
39+
)

martian/test/sum_squares/sum_squares.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//go:generate mro2go -p main -o types.go ../sum_squares.mro
1+
//go:generate -command m2g /usr/bin/env MROPATH=.. go run github.com/martian-lang/martian/cmd/mro2go
2+
//go:generate m2g -p main -o types.go sum_squares.mro
23

34
package main
45

martian/test/sum_squares/types.go

+21-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/split_test_go/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ mro_library(
3636
name = "pipeline_stages",
3737
testonly = True,
3838
srcs = ["pipeline_stages.mro"],
39+
mropath = ".",
40+
visibility = ["//martian/test/pipeline_gen:__pkg__"],
3941
deps = [
4042
"//:sum_squares",
4143
"//test/split_test_go/stages/report",

0 commit comments

Comments
 (0)