Skip to content

Commit

Permalink
make patch consts work for go1.22
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed Apr 7, 2024
1 parent 6d0b957 commit 5e64b66
Show file tree
Hide file tree
Showing 18 changed files with 1,136 additions and 165 deletions.
13 changes: 13 additions & 0 deletions cmd/xgo/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ func addContentAt(content string, beginMark string, endMark string, seq []string
return insertContentNoDuplicate(content, beginMark, endMark, idx, addContent)
}

func addContentAtIndex(content string, beginMark string, endMark string, seq []string, i int, before bool, addContent string) string {
offset, endOffset := strutil.SeqenceOffset(content, seq, i, before)
if offset < 0 {
panic(fmt.Errorf("sequence missing: %v", seq))
}
anotherOff, _ := strutil.SeqenceOffset(content[endOffset:], seq, i, false)
if anotherOff >= 0 {
panic(fmt.Errorf("sequence duplicate: %v", seq))
}
return insertContentNoDuplicate(content, beginMark, endMark, offset, addContent)
}

func replaceContentAfter(content string, beginMark string, endMark string, seq []string, target string, replaceContent string) string {
if replaceContent == "" {
return content
Expand All @@ -72,6 +84,7 @@ func replaceContentAfter(content string, beginMark string, endMark string, seq [
}

// signature example: /*<begin ident>*/ {content} /*<end ident>*/
// insert content at index
func insertContentNoDuplicate(content string, beginMark string, endMark string, idx int, insertContent string) string {
if insertContent == "" {
return content
Expand Down
2 changes: 1 addition & 1 deletion cmd/xgo/exec_tool/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (c *VscodeDebugConfig) ToMap() (map[string]interface{}, error) {
}

const vscodeRemoteDebug = `{
"name": "dlv remoe localhost:2345",
"name": "dlv remote localhost:2345",
"type": "go",
"request": "attach",
"mode": "remote",
Expand Down
57 changes: 37 additions & 20 deletions cmd/xgo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func handleBuild(cmd string, args []string) error {
logStartup()
}

goroot, err := checkGoroot(withGoroot)
goroot, err := checkGoroot(projectDir, withGoroot)
if err != nil {
return err
}
Expand Down Expand Up @@ -526,29 +526,46 @@ func getXgoHome(xgoHome string) (string, error) {
return absHome, nil
}

func checkGoroot(goroot string) (string, error) {
func getGoEnvRoot(dir string) (string, error) {
goroot, err := cmd.Dir(dir).Output("go", "env", "GOROOT")
if err != nil {
return "", err
}
// remove special characters from output
goroot = strings.ReplaceAll(goroot, "\n", "")
goroot = strings.ReplaceAll(goroot, "\r", "")
return goroot, nil
}

func checkGoroot(dir string, goroot string) (string, error) {
if goroot == "" {
// use env first because dir will affect the actual
// go version used
// because with new go toolchain mechanism, even with:
// which go -> /Users/xhd2015/installed/go1.21.7/bin/go
// the actual go still points to go1.22.0
// go version ->
// go tool chain: https://go.dev/doc/toolchain
// GOTOOLCHAIN=auto
envGoroot, envErr := getGoEnvRoot(dir)
if envErr == nil && envGoroot != "" {
return envGoroot, nil
}
goroot = runtime.GOROOT()
if goroot == "" {
envGoroot, err := cmd.Output("go", "env", "GOROOT")
if err != nil {
var errMsg string
if e, ok := err.(*exec.ExitError); ok {
errMsg = string(e.Stderr)
} else {
errMsg = err.Error()
}
return "", fmt.Errorf("requires GOROOT or --with-goroot: go env GOROOT: %v", errMsg)
}
// remove special characters from output
envGoroot = strings.ReplaceAll(envGoroot, "\n", "")
envGoroot = strings.ReplaceAll(envGoroot, "\r", "")
goroot = envGoroot
if goroot != "" {
return goroot, nil
}
if goroot == "" {
return "", fmt.Errorf("requires GOROOT or --with-goroot")

if envErr != nil {
var errMsg string
if e, ok := envErr.(*exec.ExitError); ok {
errMsg = string(e.Stderr)
} else {
errMsg = envErr.Error()
}
return "", fmt.Errorf("requires GOROOT or --with-goroot: go env GOROOT: %v", errMsg)
}
return goroot, nil
return "", fmt.Errorf("requires GOROOT or --with-goroot")
}
_, err := os.Stat(goroot)
if err == nil {
Expand Down
10 changes: 10 additions & 0 deletions cmd/xgo/patch_compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ var compilerFiles = []_FilePath{
compilerRuntimeDefFile,
compilerRuntimeDefFile18,
compilerRuntimeDefFile16,

type2ExprPatch.FilePath,
type2AssignmentsPatch.FilePath,
syntaxWalkPatch.FilePath,
noderWriterPatch.FilePath,
syntaxExtra,
}

func patchCompiler(origGoroot string, goroot string, goVersion *goinfo.GoVersion, xgoSrc string, forceReset bool, syncWithLink bool) error {
Expand Down Expand Up @@ -94,6 +100,10 @@ func patchCompilerInternal(goroot string, goVersion *goinfo.GoVersion) error {
if err != nil {
return fmt.Errorf("patching gc main:%w", err)
}
err = patchCompilerAstTypeCheck(goroot)
if err != nil {
return fmt.Errorf("patch ast type check:%w", err)
}
return nil
}

Expand Down
218 changes: 218 additions & 0 deletions cmd/xgo/patch_compiler_ast_type_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package main

import "os"

const convertXY = `
if xgoConv, ok := x.expr.(*syntax.XgoSimpleConvert); ok {
var isConst bool
switch y.expr.(type) {
case *syntax.XgoSimpleConvert,*syntax.BasicLit:
isConst=true
}
if !isConst{
t := y.typ
callExpr := xgoConv.X.(*syntax.CallExpr)
ct := callExpr.GetTypeInfo()
ct.Type = t
callExpr.SetTypeInfo(ct)
name := callExpr.Fun.(*syntax.Name)
nt := name.GetTypeInfo()
nt.Type = t
name.SetTypeInfo(nt)
name.Value = t.String()
xt := xgoConv.GetTypeInfo()
xt.Type = t
xgoConv.SetTypeInfo(xt)
x.typ = t
}
}else if xgoConv,ok := y.expr.(*syntax.XgoSimpleConvert);ok {
var isConst bool
switch x.expr.(type) {
case *syntax.XgoSimpleConvert,*syntax.BasicLit:
isConst=true
}
if !isConst{
t := x.typ
callExpr := xgoConv.X.(*syntax.CallExpr)
ct := callExpr.GetTypeInfo()
ct.Type = t
callExpr.SetTypeInfo(ct)
name := callExpr.Fun.(*syntax.Name)
nt := name.GetTypeInfo()
nt.Type = t
name.SetTypeInfo(nt)
name.Value = t.String()
xt := xgoConv.GetTypeInfo()
xt.Type = t
xgoConv.SetTypeInfo(xt)
y.typ = t
}
}
`

var type2ExprPatch = &FilePatch{
FilePath: _FilePath{"src", "cmd", "compile", "internal", "types2", "expr.go"},
Patches: []*Patch{
{
Mark: "type2_check_xgo_simple_convert",
InsertIndex: 5,
InsertBefore: true,
Anchors: []string{
`(check *Checker) exprInternal`,
"\n",
`default:`,
`case *syntax.Operation:`,
`case *syntax.KeyValueExpr:`,
`default:`,
"\n",
},
Content: `
case *syntax.XgoSimpleConvert:
kind := check.rawExpr(nil, x, e.X, nil, false)
x.expr = e
return kind
`,
},
{
Mark: "type2_match_type_xgo_simple_convert",
InsertIndex: 1,
Anchors: []string{
`func (check *Checker) matchTypes(x, y *operand) {`,
"\n",
},
Content: convertXY,
},
{
Mark: "type2_comparison_xgo_simple_convert",
InsertIndex: 2,
Anchors: []string{
`func (check *Checker) comparison(x, y *operand`,
"{",
"\n",
},
Content: convertXY,
},
},
}

var type2AssignmentsPatch = &FilePatch{
FilePath: _FilePath{"src", "cmd", "compile", "internal", "types2", "assignments.go"},
Patches: []*Patch{
{
Mark: "type2_assignment_rewrite_xgo_simple_convert",
InsertIndex: 1,
InsertBefore: true,
Anchors: []string{
`func (check *Checker) assignment(`,
`switch x.mode {`,
},
Content: `
if xgoConv, ok := x.expr.(*syntax.XgoSimpleConvert); ok {
callExpr := xgoConv.X.(*syntax.CallExpr)
funName := callExpr.Fun.(*syntax.Name)
t := funName.GetTypeInfo()
t.Type = T
funName.SetTypeInfo(t)
funName.Value = T.String()
ct := callExpr.GetTypeInfo()
ct.Type = T
callExpr.SetTypeInfo(ct)
x.expr = callExpr
x.typ = T
xt := xgoConv.GetTypeInfo()
xt.Type = T
xgoConv.SetTypeInfo(xt)
}
`,
},
},
}

var syntaxWalkPatch = &FilePatch{
FilePath: _FilePath{"src", "cmd", "compile", "internal", "syntax", "walk.go"},
Patches: []*Patch{
{
Mark: "syntax_walk_xgo_simple_convert",
InsertIndex: 4,
InsertBefore: true,
Anchors: []string{
`func (w walker) node(n Node) {`,
`case *RangeClause:`,
`case *CaseClause:`,
`case *CommClause:`,
`default`,
},
Content: `
case *XgoSimpleConvert:
w.node(n.X)
`,
},
},
}

var noderWriterPatch = &FilePatch{
FilePath: _FilePath{"src", "cmd", "compile", "internal", "noder", "writer.go"},
Patches: []*Patch{
{
Mark: "noder_write_xgo_simple_convert",
InsertIndex: 3,
InsertBefore: true,
Anchors: []string{
`func (w *writer) expr(expr syntax.Expr) {`,
`switch expr := expr.(type) {`,
`case *syntax.Operation:`,
`case *syntax.CallExpr:`,
},
Content: `
case *syntax.XgoSimpleConvert:
w.expr(expr.X)
`,
},
},
}
var syntaxExtra = _FilePath{"src", "cmd", "compile", "internal", "syntax", "xgo_extra.go"}

const syntaxExtraPatch = `
package syntax
// helper: convert anything to which
// the type is expected
type XgoSimpleConvert struct {
X Expr
expr
}
`

func patchCompilerAstTypeCheck(goroot string) error {
err := type2ExprPatch.Apply(goroot)
if err != nil {
return err
}
err = type2AssignmentsPatch.Apply(goroot)
if err != nil {
return err
}
err = syntaxWalkPatch.Apply(goroot)
if err != nil {
return err
}
err = noderWriterPatch.Apply(goroot)
if err != nil {
return err
}
syntaxExtraFile := syntaxExtra.Join(goroot)
err = os.WriteFile(syntaxExtraFile, []byte(syntaxExtraPatch), 0755)
if err != nil {
return err
}
return nil
}
Loading

0 comments on commit 5e64b66

Please sign in to comment.