Skip to content

Commit

Permalink
fix handling of plus build lines
Browse files Browse the repository at this point in the history
Signed-off-by: Achille Roussel <[email protected]>
  • Loading branch information
achille-roussel committed Sep 25, 2023
1 parent be47365 commit 8087b8a
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 33 deletions.
26 changes: 0 additions & 26 deletions compiler/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ package compiler

import (
"go/ast"
"go/build/constraint"
"slices"
"strings"
)

func appendCommentGroup(comments []*ast.Comment, group *ast.CommentGroup) []*ast.Comment {
Expand Down Expand Up @@ -33,26 +30,3 @@ func commentGroupsOf(file *ast.File) []*ast.CommentGroup {
}
return groups
}

const gobuild = "//go:build"

func parseBuildTags(file *ast.File) (constraint.Expr, error) {
for _, group := range commentGroupsOf(file) {
for _, comment := range group.List {
if strings.HasPrefix(comment.Text, gobuild) {
return constraint.Parse(comment.Text)
}
}
}
return nil, nil
}

func stripBuildTagsOf(file *ast.File) {
for _, group := range commentGroupsOf(file) {
for i, comment := range group.List {
if strings.HasPrefix(comment.Text, gobuild) {
group.List = slices.Delete(group.List, i, i+1)
}
}
}
}
15 changes: 8 additions & 7 deletions compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,12 @@ func (c *compiler) compile(path string) error {
}

func (c *compiler) writeFile(path string, file *ast.File, changeBuildTags func(constraint.Expr) constraint.Expr) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()

buildTags, err := parseBuildTags(file)
if err != nil {
return err
}
buildTags = changeBuildTags(buildTags)
stripBuildTagsOf(file)
stripBuildTagsOf(file, path)

// Comments are awkward to attach to the tree (they rely on token.Pos, which
// is coupled to a token.FileSet). Instead, just write out the raw strings.
Expand All @@ -207,6 +201,13 @@ func (c *compiler) writeFile(path string, file *ast.File, changeBuildTags func(c
b.WriteString(buildTags.String())
b.WriteString("\n\n")
}

f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()

if _, err := f.WriteString(b.String()); err != nil {
return err
}
Expand Down
41 changes: 41 additions & 0 deletions compiler/constraint.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package compiler

import (
"go/ast"
"go/build/constraint"
"reflect"
"slices"
)

func containsExpr(expr, contains constraint.Expr) bool {
Expand Down Expand Up @@ -36,3 +38,42 @@ func withoutBuildTag(expr constraint.Expr, buildTag *constraint.TagExpr) constra
return &constraint.AndExpr{X: expr, Y: notBuildTag}
}
}

func parseBuildTags(file *ast.File) (constraint.Expr, error) {
groups := commentGroupsOf(file)

for _, group := range groups {
for _, c := range group.List {
if constraint.IsGoBuild(c.Text) {
return constraint.Parse(c.Text)
}
}
}

var plusBuildLines constraint.Expr
for _, group := range groups {
for _, c := range group.List {
if constraint.IsPlusBuild(c.Text) {
x, err := constraint.Parse(c.Text)
if err != nil {
return nil, err
}
if plusBuildLines == nil {
plusBuildLines = x
} else {
plusBuildLines = &constraint.AndExpr{X: plusBuildLines, Y: x}
}
}
}
}

return plusBuildLines, nil
}

func stripBuildTagsOf(file *ast.File, path string) {
for _, group := range commentGroupsOf(file) {
group.List = slices.DeleteFunc(group.List, func(c *ast.Comment) bool {
return constraint.IsGoBuild(c.Text) || constraint.IsPlusBuild(c.Text)
})
}
}
2 changes: 2 additions & 0 deletions compiler/testdata/http/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !durable

package main

import (
Expand Down
106 changes: 106 additions & 0 deletions compiler/testdata/http/main_generated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//go:build durable

package main

import (
http "net/http"
coroutine "github.com/stealthrocket/coroutine"
fmt "fmt"
)
import _types "github.com/stealthrocket/coroutine/types"

type yieldingRoundTripper struct {
}
//go:noinline
func RoundTrip(req *http.Request) (_ *http.Response, _ error) {
_c := coroutine.LoadContext[*http.Request, *http.Response]()
_f, _fp := _c.Push()
var _f0 *struct {
X0 *http.Request
X1 *http.Response
}
if _f.IP == 0 {
_f0 = &struct {
X0 *http.Request
X1 *http.Response
}{X0: req}
} else {
_f0 = _f.Get(0).(*struct {
X0 *http.Request
X1 *http.Response
})
}
defer func() {
if _c.Unwinding() {
_f.Set(0, _f0)
_c.Store(_fp, _f)
} else {
_c.Pop()
}
}()
switch {
case _f.IP < 2:
_f0.X1 = coroutine.Yield[*http.Request, *http.Response](_f0.X0)
_f.IP = 2
fallthrough
case _f.IP < 3:
return _f0.X1, nil
}
return
}
//go:noinline
func work() {
_c := coroutine.LoadContext[*http.Request, *http.Response]()
_f, _fp := _c.Push()
var _f0 *struct {
X0 *http.Response
X1 error
}
if _f.IP == 0 {
_f0 = &struct {
X0 *http.Response
X1 error
}{}
} else {
_f0 = _f.Get(0).(*struct {
X0 *http.Response
X1 error
})
}
defer func() {
if _c.Unwinding() {
_f.Set(0, _f0)
_c.Store(_fp, _f)
} else {
_c.Pop()
}
}()
switch {
case _f.IP < 2:
_f0.X0, _f0.X1 = http.Get("http://example.com")
_f.IP = 2
fallthrough
case _f.IP < 3:
if _f0.X1 != nil {
panic(_f0.X1)
}
_f.IP = 3
fallthrough
case _f.IP < 4:
fmt.Println(_f0.X0.StatusCode)
}
}
func main() {
http.DefaultTransport = &yieldingRoundTripper{}
c := coroutine.New[*http.Request, *http.Response](work)
for c.Next() {
req := c.Recv()
fmt.Println("Requesting", req.URL.String())
c.Send(&http.Response{StatusCode: 200})
}
}
func init() {
_types.RegisterFunc[func(req *http.Request) (_ *http.Response, _ error)]("github.com/stealthrocket/coroutine/compiler/testdata/http.RoundTrip")
_types.RegisterFunc[func()]("github.com/stealthrocket/coroutine/compiler/testdata/http.main")
_types.RegisterFunc[func()]("github.com/stealthrocket/coroutine/compiler/testdata/http.work")
}

0 comments on commit 8087b8a

Please sign in to comment.