├── .github ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .goreleaser.yaml ├── LICENSE ├── README.md ├── cmd ├── root.go └── version.go ├── go.mod ├── go.sum ├── internal └── mingo │ ├── decl.go │ ├── expr.go │ ├── file.go │ ├── func.go │ ├── mingo.go │ ├── mingo_test.go │ ├── stmt.go │ └── testdata │ ├── const │ ├── expected │ └── main.go │ ├── for │ ├── expected │ └── main.go │ ├── func │ ├── expected │ └── main.go │ ├── generic │ ├── expected │ └── main.go │ ├── go │ ├── expected │ └── main.go │ ├── goto │ ├── expected │ └── main.go │ ├── if │ ├── expected │ └── main.go │ ├── incdec │ ├── expected │ └── main.go │ ├── interface │ ├── expected │ └── main.go │ ├── range │ ├── expected │ └── main.go │ ├── slice │ ├── expected │ └── main.go │ ├── struct │ ├── expected │ └── main.go │ ├── switch │ ├── expected │ └── main.go │ └── var │ ├── expected │ └── main.go └── main.go /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - uses: actions/setup-go@v4 7 | with: 8 | go-version-file: go.mod 9 | cache: true 10 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | - name: Setup 13 | uses: ./.github/actions/setup 14 | - name: Test 15 | run: go test ./... -race -coverprofile=coverage.out -covermode=atomic 16 | 17 | build: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | - name: Setup 23 | uses: ./.github/actions/setup 24 | - name: Build 25 | run: go build . 26 | 27 | lint: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | - name: Setup 33 | uses: ./.github/actions/setup 34 | - name: Lint 35 | uses: golangci/golangci-lint-action@v4 36 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | - name: Setup 19 | uses: ./.github/actions/setup 20 | - name: Release 21 | uses: goreleaser/goreleaser-action@v4 22 | with: 23 | args: release --clean 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /mingo 2 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod tidy 4 | builds: 5 | - ldflags: 6 | - -s -w -X github.com/koki-develop/mingo/cmd.version=v{{.Version}} 7 | env: 8 | - CGO_ENABLED=0 9 | goos: 10 | - linux 11 | - windows 12 | - darwin 13 | 14 | archives: 15 | - format: tar.gz 16 | name_template: >- 17 | {{ .ProjectName }}_ 18 | {{- title .Os }}_ 19 | {{- if eq .Arch "amd64" }}x86_64 20 | {{- else if eq .Arch "386" }}i386 21 | {{- else }}{{ .Arch }}{{ end }} 22 | {{- if .Arm }}v{{ .Arm }}{{ end }} 23 | format_overrides: 24 | - goos: windows 25 | format: zip 26 | checksum: 27 | name_template: 'checksums.txt' 28 | snapshot: 29 | name_template: "{{ incpatch .Version }}-next" 30 | changelog: 31 | sort: asc 32 | filters: 33 | exclude: 34 | - '^docs:' 35 | - '^test:' 36 | 37 | brews: 38 | - repository: 39 | owner: koki-develop 40 | name: homebrew-tap 41 | token: "{{ .Env.TAP_GITHUB_TOKEN }}" 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Koki Sato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

mingo

2 | 3 |

4 | GitHub release (latest by date) 5 | GitHub Workflow Status 6 | Go Report Card 7 | LICENSE 8 |

9 | 10 |

11 | Go also wants to be minified. 12 |

13 | 14 | ## Contents 15 | 16 | - [Contents](#contents) 17 | - [Installation](#installation) 18 | - [Homebrew Tap](#homebrew-tap) 19 | - [`go install`](#go-install) 20 | - [Releases](#releases) 21 | - [Usage](#usage) 22 | - [Example](#example) 23 | - [LICENSE](#license) 24 | 25 | ## Installation 26 | 27 | ### Homebrew Tap 28 | 29 | ```console 30 | $ brew install koki-develop/tap/mingo 31 | ``` 32 | 33 | ### `go install` 34 | 35 | ```console 36 | $ go install github.com/koki-develop/mingo@latest 37 | ``` 38 | 39 | ### Releases 40 | 41 | Download the binary from the [releases page](https://github.com/koki-develop/mingo/releases/latest). 42 | 43 | ## Usage 44 | 45 | ```console 46 | $ mingo --help 47 | Go language also wants to be minified. 48 | 49 | Usage: 50 | mingo [flags] [files]... 51 | 52 | Flags: 53 | -h, --help help for mingo 54 | -v, --version version for mingo 55 | -w, --write write result to (source) file instead of stdout 56 | ``` 57 | 58 | ### Example 59 | 60 | ```go 61 | // main.go 62 | package main 63 | 64 | import "fmt" 65 | 66 | func fib(n int) int { 67 | if n <= 1 { 68 | return n 69 | } 70 | return fib(n-1) + fib(n-2) 71 | } 72 | 73 | func main() { 74 | n := 10 75 | for i := 0; i < n; i++ { 76 | fmt.Println(fib(i)) 77 | } 78 | } 79 | ``` 80 | 81 | ```console 82 | $ mingo main.go 83 | ``` 84 | 85 | ```go 86 | package main;import "fmt";func fib(n int)int{if n<=1{return n};return fib(n-1)+fib(n-2)};func main(){n:=10;for i:=0;i 1 { 40 | sb.WriteString("(") 41 | } else { 42 | sb.WriteString(" ") 43 | } 44 | 45 | for i, n := range decl.Specs { 46 | n := n.(*ast.ImportSpec) 47 | 48 | if i > 0 { 49 | sb.WriteString(";") 50 | } 51 | if n.Name != nil { 52 | sb.WriteString(fmt.Sprintf("%s %s", n.Name.Name, n.Path.Value)) 53 | } else { 54 | sb.WriteString(n.Path.Value) 55 | } 56 | } 57 | 58 | if len(decl.Specs) > 1 { 59 | sb.WriteString(")") 60 | } 61 | sb.WriteString(";") 62 | return sb.String() 63 | } 64 | 65 | func (m *mingo) stringifyConstDecl(decl *ast.GenDecl) string { 66 | sb := new(strings.Builder) 67 | sb.WriteString("const") 68 | 69 | if len(decl.Specs) > 1 { 70 | sb.WriteString("(") 71 | } else { 72 | sb.WriteString(" ") 73 | } 74 | 75 | for i, spec := range decl.Specs { 76 | spec := spec.(*ast.ValueSpec) 77 | 78 | if i > 0 { 79 | sb.WriteString(";") 80 | } 81 | for j, name := range spec.Names { 82 | if j > 0 { 83 | sb.WriteString(",") 84 | } 85 | sb.WriteString(name.Name) 86 | } 87 | 88 | if spec.Type != nil { 89 | sb.WriteString(" ") 90 | sb.WriteString(m.stringifyExpr(spec.Type)) 91 | } 92 | 93 | if spec.Values != nil { 94 | sb.WriteString("=") 95 | for k, value := range spec.Values { 96 | if k > 0 { 97 | sb.WriteString(",") 98 | } 99 | sb.WriteString(m.stringifyExpr(value)) 100 | } 101 | } 102 | } 103 | 104 | if len(decl.Specs) > 1 { 105 | sb.WriteString(")") 106 | } 107 | sb.WriteString(";") 108 | return sb.String() 109 | } 110 | 111 | func (m *mingo) stringifyVarDecl(decl *ast.GenDecl) string { 112 | sb := new(strings.Builder) 113 | 114 | if decl.Doc != nil { 115 | for _, cmt := range decl.Doc.List { 116 | if strings.HasPrefix(cmt.Text, "//go:embed ") { 117 | fmt.Fprintf(sb, "\n%s\n", cmt.Text) 118 | } 119 | } 120 | } 121 | 122 | sb.WriteString("var") 123 | 124 | if len(decl.Specs) > 1 { 125 | sb.WriteString("(") 126 | } else { 127 | sb.WriteString(" ") 128 | } 129 | 130 | for i, spec := range decl.Specs { 131 | spec := spec.(*ast.ValueSpec) 132 | 133 | if i > 0 { 134 | sb.WriteString(";") 135 | } 136 | for j, name := range spec.Names { 137 | if j > 0 { 138 | sb.WriteString(",") 139 | } 140 | 141 | if spec.Doc != nil { 142 | for _, cmt := range spec.Doc.List { 143 | if strings.HasPrefix(cmt.Text, "//go:embed ") { 144 | fmt.Fprintf(sb, "\n%s\n", cmt.Text) 145 | } 146 | } 147 | } 148 | sb.WriteString(name.Name) 149 | } 150 | 151 | if spec.Type != nil { 152 | sb.WriteString(" ") 153 | sb.WriteString(m.stringifyExpr(spec.Type)) 154 | } 155 | 156 | if spec.Values != nil { 157 | sb.WriteString("=") 158 | for k, value := range spec.Values { 159 | if k > 0 { 160 | sb.WriteString(",") 161 | } 162 | sb.WriteString(m.stringifyExpr(value)) 163 | } 164 | } 165 | } 166 | 167 | if len(decl.Specs) > 1 { 168 | sb.WriteString(")") 169 | } 170 | sb.WriteString(";") 171 | return sb.String() 172 | } 173 | 174 | func (m *mingo) stringifyTypeSpec(decl *ast.GenDecl) string { 175 | sb := new(strings.Builder) 176 | 177 | for _, n := range decl.Specs { 178 | n := n.(*ast.TypeSpec) 179 | 180 | sb.WriteString(fmt.Sprintf("type %s", n.Name.Name)) 181 | if n.TypeParams != nil { 182 | sb.WriteString(m.stringifyFuncTypeParams(n.TypeParams)) 183 | } 184 | if n.Assign != 0 { 185 | sb.WriteString("=") 186 | } else { 187 | sb.WriteString(" ") 188 | } 189 | sb.WriteString(m.stringifyExpr(n.Type)) 190 | sb.WriteString(";") 191 | } 192 | 193 | return sb.String() 194 | } 195 | -------------------------------------------------------------------------------- /internal/mingo/expr.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "strings" 7 | ) 8 | 9 | func (m *mingo) stringifyExpr(expr ast.Expr) string { 10 | switch x := expr.(type) { 11 | case *ast.BasicLit: 12 | return m.stringifyBasicLit(x) 13 | case *ast.CallExpr: 14 | return m.stringifyCallExpr(x) 15 | case *ast.SelectorExpr: 16 | return m.stringifySelectExpr(x) 17 | case *ast.StarExpr: 18 | return m.stringifyStarExpr(x) 19 | case *ast.ArrayType: 20 | return m.stringifyArrayType(x) 21 | case *ast.Ellipsis: 22 | return m.stringifyEllipsis(x) 23 | case *ast.FuncLit: 24 | return m.stringifyFuncLit(x) 25 | case *ast.BinaryExpr: 26 | return m.stringifyBinaryExpr(x) 27 | case *ast.SliceExpr: 28 | return m.stringifySliceExpr(x) 29 | case *ast.UnaryExpr: 30 | return m.stringifyUnaryExpr(x) 31 | case *ast.CompositeLit: 32 | return m.stringifyCompositeLit(x) 33 | case *ast.ParenExpr: 34 | return m.stringifyParenExpr(x) 35 | case *ast.IndexExpr: 36 | return m.stringifyIndexExpr(x) 37 | case *ast.KeyValueExpr: 38 | return m.stringifyKeyValueExpr(x) 39 | case *ast.TypeAssertExpr: 40 | return m.stringifyTypeAssertExpr(x) 41 | case *ast.ChanType: 42 | return m.stringifyChanType(x) 43 | case *ast.MapType: 44 | return m.stringifyMapType(x) 45 | case *ast.InterfaceType: 46 | return m.stringifyInterfaceType(x) 47 | case *ast.StructType: 48 | return m.stringifyStructType(x) 49 | case *ast.FuncType: 50 | return m.stringifyFuncType(x) 51 | case *ast.IndexListExpr: 52 | return m.stringifyIndexListExpr(x) 53 | case nil: 54 | return "" 55 | } 56 | 57 | return expr.(*ast.Ident).Name 58 | } 59 | 60 | func (m *mingo) stringifyIndexListExpr(expr *ast.IndexListExpr) string { 61 | sb := new(strings.Builder) 62 | 63 | sb.WriteString(m.stringifyExpr(expr.X)) 64 | sb.WriteString("[") 65 | for i, index := range expr.Indices { 66 | if i > 0 { 67 | sb.WriteString(",") 68 | } 69 | sb.WriteString(m.stringifyExpr(index)) 70 | } 71 | sb.WriteString("]") 72 | 73 | return sb.String() 74 | } 75 | 76 | func (m *mingo) stringifySelectExpr(expr *ast.SelectorExpr) string { 77 | switch x := expr.X.(type) { 78 | case *ast.SelectorExpr: 79 | return fmt.Sprintf("%s.%s", m.stringifySelectExpr(x), expr.Sel.Name) 80 | default: 81 | return fmt.Sprintf("%s.%s", m.stringifyExpr(expr.X), expr.Sel.Name) 82 | } 83 | } 84 | 85 | func (m *mingo) stringifyBasicLit(lit *ast.BasicLit) string { 86 | return lit.Value 87 | } 88 | 89 | func (m *mingo) stringifyCallExpr(expr *ast.CallExpr) string { 90 | sb := new(strings.Builder) 91 | 92 | sb.WriteString(m.stringifyExpr(expr.Fun)) 93 | sb.WriteString("(") 94 | for i, arg := range expr.Args { 95 | if i > 0 { 96 | sb.WriteString(",") 97 | } 98 | sb.WriteString(m.stringifyExpr(arg)) 99 | } 100 | 101 | if expr.Ellipsis.IsValid() { 102 | sb.WriteString("...") 103 | } 104 | 105 | sb.WriteString(")") 106 | 107 | return sb.String() 108 | } 109 | 110 | func (m *mingo) stringifyStarExpr(expr *ast.StarExpr) string { 111 | return fmt.Sprintf("*%s", m.stringifyExpr(expr.X)) 112 | } 113 | 114 | func (m *mingo) stringifyArrayType(expr *ast.ArrayType) string { 115 | return fmt.Sprintf("[]%s", m.stringifyExpr(expr.Elt)) 116 | } 117 | 118 | func (m *mingo) stringifyEllipsis(expr *ast.Ellipsis) string { 119 | return fmt.Sprintf("...%s", m.stringifyExpr(expr.Elt)) 120 | } 121 | 122 | func (m *mingo) stringifyFuncLit(expr *ast.FuncLit) string { 123 | sb := new(strings.Builder) 124 | sb.WriteString(m.stringifyFuncType(expr.Type)) 125 | sb.WriteString(m.stringifyBlockStmt(expr.Body)) 126 | 127 | return sb.String() 128 | } 129 | 130 | func (m *mingo) stringifyBinaryExpr(expr *ast.BinaryExpr) string { 131 | return fmt.Sprintf("%s%s%s", m.stringifyExpr(expr.X), expr.Op.String(), m.stringifyExpr(expr.Y)) 132 | } 133 | 134 | func (m *mingo) stringifySliceExpr(expr *ast.SliceExpr) string { 135 | sb := new(strings.Builder) 136 | 137 | sb.WriteString(m.stringifyExpr(expr.X)) 138 | sb.WriteString("[") 139 | if expr.Low != nil { 140 | sb.WriteString(m.stringifyExpr(expr.Low)) 141 | } 142 | sb.WriteString(":") 143 | if expr.High != nil { 144 | sb.WriteString(m.stringifyExpr(expr.High)) 145 | } 146 | if expr.Max != nil { 147 | sb.WriteString(":") 148 | sb.WriteString(m.stringifyExpr(expr.Max)) 149 | } 150 | sb.WriteString("]") 151 | 152 | return sb.String() 153 | } 154 | 155 | func (m *mingo) stringifyUnaryExpr(expr *ast.UnaryExpr) string { 156 | return fmt.Sprintf("%s%s", expr.Op.String(), m.stringifyExpr(expr.X)) 157 | } 158 | 159 | func (m *mingo) stringifyCompositeLit(expr *ast.CompositeLit) string { 160 | sb := new(strings.Builder) 161 | 162 | sb.WriteString(m.stringifyExpr(expr.Type)) 163 | sb.WriteString("{") 164 | for i, elt := range expr.Elts { 165 | if i > 0 { 166 | sb.WriteString(",") 167 | } 168 | sb.WriteString(m.stringifyExpr(elt)) 169 | } 170 | sb.WriteString("}") 171 | 172 | return sb.String() 173 | } 174 | 175 | func (m *mingo) stringifyParenExpr(expr *ast.ParenExpr) string { 176 | return fmt.Sprintf("(%s)", m.stringifyExpr(expr.X)) 177 | } 178 | 179 | func (m *mingo) stringifyIndexExpr(expr *ast.IndexExpr) string { 180 | return fmt.Sprintf("%s[%s]", m.stringifyExpr(expr.X), m.stringifyExpr(expr.Index)) 181 | } 182 | 183 | func (m *mingo) stringifyKeyValueExpr(expr *ast.KeyValueExpr) string { 184 | return fmt.Sprintf("%s:%s", m.stringifyExpr(expr.Key), m.stringifyExpr(expr.Value)) 185 | } 186 | 187 | func (m *mingo) stringifyTypeAssertExpr(expr *ast.TypeAssertExpr) string { 188 | if expr.Type == nil { 189 | return fmt.Sprintf("%s.(type)", m.stringifyExpr(expr.X)) 190 | } else { 191 | return fmt.Sprintf("%s.(%s)", m.stringifyExpr(expr.X), m.stringifyExpr(expr.Type)) 192 | } 193 | } 194 | 195 | func (m *mingo) stringifyChanType(expr *ast.ChanType) string { 196 | sb := new(strings.Builder) 197 | 198 | if expr.Dir == ast.RECV { 199 | sb.WriteString("<-") 200 | } 201 | sb.WriteString("chan ") 202 | sb.WriteString(m.stringifyExpr(expr.Value)) 203 | 204 | return sb.String() 205 | } 206 | 207 | func (m *mingo) stringifyMapType(expr *ast.MapType) string { 208 | return fmt.Sprintf("map[%s]%s", m.stringifyExpr(expr.Key), m.stringifyExpr(expr.Value)) 209 | } 210 | 211 | func (m *mingo) stringifyInterfaceType(expr *ast.InterfaceType) string { 212 | sb := new(strings.Builder) 213 | 214 | sb.WriteString("interface{") 215 | for i, field := range expr.Methods.List { 216 | if i > 0 { 217 | sb.WriteString(";") 218 | } 219 | for _, name := range field.Names { 220 | sb.WriteString(name.Name) 221 | } 222 | if f, ok := field.Type.(*ast.FuncType); ok { 223 | sb.WriteString(m.stringifyFuncTypeParams(f.TypeParams)) 224 | sb.WriteString(m.stringifyFuncParams(f.Params)) 225 | sb.WriteString(m.stringifyFuncResults(f.Results)) 226 | } else { 227 | sb.WriteString(m.stringifyExpr(field.Type)) 228 | } 229 | } 230 | sb.WriteString("}") 231 | 232 | return sb.String() 233 | } 234 | 235 | func (m *mingo) stringifyStructType(expr *ast.StructType) string { 236 | sb := new(strings.Builder) 237 | 238 | sb.WriteString("struct{") 239 | for i, field := range expr.Fields.List { 240 | if i > 0 { 241 | sb.WriteString(";") 242 | } 243 | for j, name := range field.Names { 244 | if j > 0 { 245 | sb.WriteString(",") 246 | } 247 | sb.WriteString(name.Name) 248 | } 249 | if len(field.Names) > 0 { 250 | sb.WriteString(" ") 251 | } 252 | sb.WriteString(m.stringifyExpr(field.Type)) 253 | 254 | if field.Tag != nil { 255 | sb.WriteString(" ") 256 | sb.WriteString(field.Tag.Value) 257 | } 258 | } 259 | sb.WriteString("}") 260 | 261 | return sb.String() 262 | } 263 | 264 | func (m *mingo) stringifyFuncType(expr *ast.FuncType) string { 265 | sb := new(strings.Builder) 266 | 267 | sb.WriteString("func") 268 | sb.WriteString(m.stringifyFuncTypeParams(expr.TypeParams)) 269 | sb.WriteString(m.stringifyFuncParams(expr.Params)) 270 | sb.WriteString(m.stringifyFuncResults(expr.Results)) 271 | 272 | return sb.String() 273 | } 274 | -------------------------------------------------------------------------------- /internal/mingo/file.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | ) 7 | 8 | func (m *mingo) stringifyFile(n *ast.File) string { 9 | return fmt.Sprintf("package %s;", n.Name.Name) 10 | } 11 | -------------------------------------------------------------------------------- /internal/mingo/func.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "strings" 7 | ) 8 | 9 | func (m *mingo) stringifyFuncDecl(n *ast.FuncDecl) string { 10 | sb := new(strings.Builder) 11 | 12 | sb.WriteString("func") 13 | 14 | if n.Recv != nil { 15 | sb.WriteString(m.stringifyFuncParams(n.Recv)) 16 | } else { 17 | sb.WriteString(" ") 18 | } 19 | 20 | fmt.Fprintf(sb, "%s", n.Name.Name) 21 | 22 | sb.WriteString(m.stringifyFuncTypeParams(n.Type.TypeParams)) 23 | sb.WriteString(m.stringifyFuncParams(n.Type.Params)) 24 | sb.WriteString(m.stringifyFuncResults(n.Type.Results)) 25 | sb.WriteString(m.stringifyBlockStmt(n.Body)) 26 | 27 | sb.WriteString(";") 28 | return sb.String() 29 | } 30 | 31 | func (m *mingo) stringifyFuncTypeParams(params *ast.FieldList) string { 32 | if params == nil { 33 | return "" 34 | } 35 | 36 | sb := new(strings.Builder) 37 | 38 | sb.WriteString("[") 39 | for i, param := range params.List { 40 | if i > 0 { 41 | sb.WriteString(",") 42 | } 43 | for j, name := range param.Names { 44 | if j > 0 { 45 | sb.WriteString(",") 46 | } 47 | sb.WriteString(name.Name) 48 | } 49 | if len(param.Names) > 0 { 50 | sb.WriteString(" ") 51 | } 52 | sb.WriteString(m.stringifyExpr(param.Type)) 53 | } 54 | sb.WriteString("]") 55 | 56 | return sb.String() 57 | } 58 | 59 | func (m *mingo) stringifyFuncParams(params *ast.FieldList) string { 60 | sb := new(strings.Builder) 61 | 62 | sb.WriteString("(") 63 | 64 | for i, arg := range params.List { 65 | if i > 0 { 66 | sb.WriteString(",") 67 | } 68 | for j, name := range arg.Names { 69 | if j > 0 { 70 | sb.WriteString(",") 71 | } 72 | sb.WriteString(name.Name) 73 | } 74 | 75 | if len(arg.Names) > 0 { 76 | sb.WriteString(" ") 77 | } 78 | 79 | sb.WriteString(m.stringifyExpr(arg.Type)) 80 | } 81 | 82 | sb.WriteString(")") 83 | return sb.String() 84 | } 85 | 86 | func (m *mingo) stringifyFuncResults(results *ast.FieldList) string { 87 | if results == nil { 88 | return "" 89 | } 90 | 91 | sb := new(strings.Builder) 92 | rb := new(strings.Builder) 93 | 94 | needParens := false 95 | if len(results.List) > 1 { 96 | needParens = true 97 | } 98 | 99 | for i, rslt := range results.List { 100 | if i > 0 { 101 | rb.WriteString(",") 102 | } 103 | 104 | for j, name := range rslt.Names { 105 | needParens = true 106 | if j > 0 { 107 | rb.WriteString(",") 108 | } 109 | rb.WriteString(name.Name) 110 | rb.WriteString(" ") 111 | } 112 | 113 | rb.WriteString(m.stringifyExpr(rslt.Type)) 114 | } 115 | 116 | if needParens { 117 | sb.WriteString("(") 118 | } 119 | sb.WriteString(rb.String()) 120 | if needParens { 121 | sb.WriteString(")") 122 | } 123 | 124 | return sb.String() 125 | } 126 | -------------------------------------------------------------------------------- /internal/mingo/mingo.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "go/format" 7 | "go/parser" 8 | "go/token" 9 | "strings" 10 | ) 11 | 12 | func Minify(filename string, src []byte) ([]byte, error) { 13 | if s, err := format.Source(src); err != nil { 14 | return nil, err 15 | } else { 16 | src = s 17 | } 18 | 19 | fset := token.NewFileSet() 20 | m := &mingo{fileSet: fset} 21 | return m.Minify(filename, src) 22 | } 23 | 24 | type mingo struct { 25 | fileSet *token.FileSet 26 | } 27 | 28 | func (m *mingo) Minify(filename string, src []byte) ([]byte, error) { 29 | file, err := parser.ParseFile(m.fileSet, filename, string(src), parser.ParseComments) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | b := new(bytes.Buffer) 35 | 36 | for _, cg := range file.Comments { 37 | for _, c := range cg.List { 38 | dirs := []string{"//go:build ", "// +build ", "//go:generate "} 39 | for _, prefix := range dirs { 40 | if strings.HasPrefix(c.Text, prefix) { 41 | fmt.Fprintln(b, c.Text) 42 | } 43 | } 44 | } 45 | } 46 | 47 | fmt.Fprint(b, m.stringifyFile(file)) 48 | for _, decl := range file.Decls { 49 | fmt.Fprint(b, m.stringifyDecl(decl)) 50 | } 51 | 52 | return b.Bytes(), nil 53 | } 54 | -------------------------------------------------------------------------------- /internal/mingo/mingo_test.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "embed" 5 | "fmt" 6 | "go/format" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | //go:embed testdata 13 | var testdata embed.FS 14 | 15 | func Test_Minify(t *testing.T) { 16 | dirs, err := testdata.ReadDir("testdata") 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | for _, dir := range dirs { 22 | t.Run(dir.Name(), func(t *testing.T) { 23 | src, err := testdata.ReadFile(fmt.Sprintf("testdata/%s/main.go", dir.Name())) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | 28 | want, err := testdata.ReadFile(fmt.Sprintf("testdata/%s/expected", dir.Name())) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | got, err := Minify("main.go", src) 34 | assert.NoError(t, err) 35 | assert.Equal(t, string(want), string(got)) 36 | 37 | // check syntax 38 | _, err = format.Source([]byte(got)) 39 | assert.NoError(t, err) 40 | }) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /internal/mingo/stmt.go: -------------------------------------------------------------------------------- 1 | package mingo 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "go/token" 7 | "strings" 8 | ) 9 | 10 | func (m *mingo) stringifyStmt(stmt ast.Stmt) string { 11 | switch x := stmt.(type) { 12 | case *ast.ReturnStmt: 13 | return m.stringifyReturnStmt(x) 14 | case *ast.AssignStmt: 15 | return m.stringifyAssignStmt(x) 16 | case *ast.IfStmt: 17 | return m.stringifyIfStmt(x) 18 | case *ast.BlockStmt: 19 | return m.stringifyBlockStmt(x) 20 | case *ast.ExprStmt: 21 | return m.stringifyExprStmt(x) 22 | case *ast.DeclStmt: 23 | return m.stringifyDeclStmt(x) 24 | case *ast.DeferStmt: 25 | return m.stringifyDeferStmt(x) 26 | case *ast.GoStmt: 27 | return m.stringifyGoStmt(x) 28 | case *ast.LabeledStmt: 29 | return m.stringifyLabeledStmt(x) 30 | case *ast.SwitchStmt: 31 | return m.stringifySwitchStmt(x) 32 | case *ast.SelectStmt: 33 | return m.stringifySelectStmt(x) 34 | case *ast.ForStmt: 35 | return m.stringifyForStmt(x) 36 | case *ast.RangeStmt: 37 | return m.stringifyRangeStmt(x) 38 | case *ast.BranchStmt: 39 | return m.stringifyBranchStmt(x) 40 | case *ast.EmptyStmt: 41 | return m.stringifyEmptyStmt(x) 42 | case *ast.IncDecStmt: 43 | return m.stringifyIncDecStmt(x) 44 | case *ast.SendStmt: 45 | return m.stringifySendStmt(x) 46 | case *ast.CaseClause: 47 | return m.stringifyCaseCaluse(x) 48 | case *ast.CommClause: 49 | return m.stringifyCommClause(x) 50 | case *ast.TypeSwitchStmt: 51 | return m.stringifyTypeSwitchStmt(x) 52 | default: 53 | panic(fmt.Sprintf("unhandled stmt: %#v", x)) 54 | } 55 | } 56 | 57 | func (m *mingo) stringifyBlockStmt(stmt *ast.BlockStmt) string { 58 | sb := new(strings.Builder) 59 | 60 | sb.WriteString("{") 61 | for i, child := range stmt.List { 62 | sb.WriteString(m.stringifyStmt(child)) 63 | 64 | if _, ok := child.(*ast.DeclStmt); !ok { 65 | if i < len(stmt.List)-1 { 66 | sb.WriteString(";") 67 | } 68 | } 69 | } 70 | sb.WriteString("}") 71 | return sb.String() 72 | } 73 | 74 | func (m *mingo) stringifyReturnStmt(stmt *ast.ReturnStmt) string { 75 | sb := new(strings.Builder) 76 | 77 | sb.WriteString("return") 78 | if len(stmt.Results) > 0 { 79 | sb.WriteString(" ") 80 | } 81 | 82 | for i, expr := range stmt.Results { 83 | if i > 0 { 84 | sb.WriteString(",") 85 | } 86 | sb.WriteString(m.stringifyExpr(expr)) 87 | } 88 | 89 | return sb.String() 90 | } 91 | 92 | func (m *mingo) stringifyAssignStmt(stmt *ast.AssignStmt) string { 93 | sb := new(strings.Builder) 94 | 95 | for i, expr := range stmt.Lhs { 96 | if i > 0 { 97 | sb.WriteString(",") 98 | } 99 | sb.WriteString(m.stringifyExpr(expr)) 100 | } 101 | if stmt.Tok == token.DEFINE { 102 | sb.WriteString(":=") 103 | } else { 104 | sb.WriteString("=") 105 | } 106 | for i, expr := range stmt.Rhs { 107 | if i > 0 { 108 | sb.WriteString(",") 109 | } 110 | sb.WriteString(m.stringifyExpr(expr)) 111 | } 112 | 113 | return sb.String() 114 | } 115 | 116 | func (m *mingo) stringifyIfStmt(stmt *ast.IfStmt) string { 117 | sb := new(strings.Builder) 118 | 119 | sb.WriteString("if ") 120 | sb.WriteString(m.stringifyIfStmtBody(stmt)) 121 | 122 | return sb.String() 123 | } 124 | 125 | func (m *mingo) stringifyElseIfStmt(stmt *ast.IfStmt) string { 126 | sb := new(strings.Builder) 127 | 128 | sb.WriteString("else if ") 129 | sb.WriteString(m.stringifyIfStmtBody(stmt)) 130 | 131 | return sb.String() 132 | } 133 | 134 | func (m *mingo) stringifyIfStmtBody(stmt *ast.IfStmt) string { 135 | sb := new(strings.Builder) 136 | 137 | if stmt.Init != nil { 138 | sb.WriteString(m.stringifyStmt(stmt.Init)) 139 | sb.WriteString(";") 140 | } 141 | if stmt.Cond != nil { 142 | sb.WriteString(m.stringifyExpr(stmt.Cond)) 143 | } 144 | if stmt.Body != nil { 145 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 146 | } 147 | if stmt.Else != nil { 148 | if ifstmt, ok := stmt.Else.(*ast.IfStmt); ok { 149 | sb.WriteString(m.stringifyElseIfStmt(ifstmt)) 150 | } else { 151 | sb.WriteString("else") 152 | sb.WriteString(m.stringifyStmt(stmt.Else)) 153 | } 154 | } 155 | 156 | return sb.String() 157 | } 158 | 159 | func (m *mingo) stringifyExprStmt(stmt *ast.ExprStmt) string { 160 | sb := new(strings.Builder) 161 | sb.WriteString(m.stringifyExpr(stmt.X)) 162 | 163 | return sb.String() 164 | } 165 | 166 | func (m *mingo) stringifyDeclStmt(stmt *ast.DeclStmt) string { 167 | sb := new(strings.Builder) 168 | sb.WriteString(m.stringifyDecl(stmt.Decl)) 169 | 170 | return sb.String() 171 | } 172 | 173 | func (m *mingo) stringifyDeferStmt(stmt *ast.DeferStmt) string { 174 | sb := new(strings.Builder) 175 | sb.WriteString("defer ") 176 | sb.WriteString(m.stringifyExpr(stmt.Call)) 177 | 178 | return sb.String() 179 | } 180 | 181 | func (m *mingo) stringifyGoStmt(stmt *ast.GoStmt) string { 182 | sb := new(strings.Builder) 183 | sb.WriteString("go ") 184 | sb.WriteString(m.stringifyExpr(stmt.Call)) 185 | 186 | return sb.String() 187 | } 188 | 189 | func (m *mingo) stringifyLabeledStmt(stmt *ast.LabeledStmt) string { 190 | sb := new(strings.Builder) 191 | sb.WriteString(fmt.Sprintf("%s:", stmt.Label.Name)) 192 | sb.WriteString(m.stringifyStmt(stmt.Stmt)) 193 | 194 | return sb.String() 195 | } 196 | 197 | func (m *mingo) stringifySwitchStmt(stmt *ast.SwitchStmt) string { 198 | sb := new(strings.Builder) 199 | sb.WriteString("switch ") 200 | if stmt.Init != nil { 201 | sb.WriteString(m.stringifyStmt(stmt.Init)) 202 | sb.WriteString(";") 203 | } 204 | if stmt.Tag != nil { 205 | sb.WriteString(m.stringifyExpr(stmt.Tag)) 206 | } 207 | if stmt.Body != nil { 208 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 209 | } 210 | 211 | return sb.String() 212 | } 213 | 214 | func (m *mingo) stringifySelectStmt(stmt *ast.SelectStmt) string { 215 | sb := new(strings.Builder) 216 | sb.WriteString("select ") 217 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 218 | 219 | return sb.String() 220 | } 221 | 222 | func (m *mingo) stringifyForStmt(stmt *ast.ForStmt) string { 223 | sb := new(strings.Builder) 224 | sb.WriteString("for ") 225 | 226 | if stmt.Init != nil { 227 | sb.WriteString(m.stringifyStmt(stmt.Init)) 228 | } 229 | if stmt.Init != nil || stmt.Post != nil { 230 | sb.WriteString(";") 231 | } 232 | if stmt.Cond != nil { 233 | sb.WriteString(m.stringifyExpr(stmt.Cond)) 234 | } 235 | if stmt.Init != nil || stmt.Post != nil { 236 | sb.WriteString(";") 237 | } 238 | if stmt.Post != nil { 239 | sb.WriteString(m.stringifyStmt(stmt.Post)) 240 | } 241 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 242 | 243 | return sb.String() 244 | } 245 | 246 | func (m *mingo) stringifyRangeStmt(stmt *ast.RangeStmt) string { 247 | sb := new(strings.Builder) 248 | sb.WriteString("for ") 249 | 250 | needAssign := false 251 | if stmt.Key != nil { 252 | needAssign = true 253 | sb.WriteString(m.stringifyExpr(stmt.Key)) 254 | } 255 | if stmt.Value != nil { 256 | needAssign = true 257 | sb.WriteString(",") 258 | sb.WriteString(m.stringifyExpr(stmt.Value)) 259 | } 260 | 261 | if needAssign { 262 | sb.WriteString(":=") 263 | } 264 | 265 | sb.WriteString("range ") 266 | sb.WriteString(m.stringifyExpr(stmt.X)) 267 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 268 | 269 | return sb.String() 270 | } 271 | 272 | func (m *mingo) stringifyBranchStmt(stmt *ast.BranchStmt) string { 273 | sb := new(strings.Builder) 274 | sb.WriteString(stmt.Tok.String()) 275 | if stmt.Label != nil { 276 | sb.WriteString(" ") 277 | sb.WriteString(stmt.Label.Name) 278 | } 279 | return sb.String() 280 | } 281 | 282 | func (m *mingo) stringifyEmptyStmt(_ *ast.EmptyStmt) string { 283 | return "" 284 | } 285 | 286 | func (m *mingo) stringifyIncDecStmt(stmt *ast.IncDecStmt) string { 287 | sb := new(strings.Builder) 288 | sb.WriteString(m.stringifyExpr(stmt.X)) 289 | sb.WriteString(stmt.Tok.String()) 290 | 291 | return sb.String() 292 | } 293 | 294 | func (m *mingo) stringifySendStmt(stmt *ast.SendStmt) string { 295 | sb := new(strings.Builder) 296 | sb.WriteString(m.stringifyExpr(stmt.Chan)) 297 | sb.WriteString("<-") 298 | sb.WriteString(m.stringifyExpr(stmt.Value)) 299 | 300 | return sb.String() 301 | } 302 | 303 | func (m *mingo) stringifyCaseCaluse(stmt *ast.CaseClause) string { 304 | sb := new(strings.Builder) 305 | 306 | if len(stmt.List) > 0 { 307 | sb.WriteString("case ") 308 | for i, expr := range stmt.List { 309 | if i > 0 { 310 | sb.WriteString(",") 311 | } 312 | sb.WriteString(m.stringifyExpr(expr)) 313 | } 314 | sb.WriteString(":") 315 | } else { 316 | sb.WriteString("default:") 317 | } 318 | for i, child := range stmt.Body { 319 | sb.WriteString(m.stringifyStmt(child)) 320 | if i < len(stmt.Body)-1 { 321 | sb.WriteString(";") 322 | } 323 | } 324 | 325 | return sb.String() 326 | } 327 | 328 | func (m *mingo) stringifyCommClause(stmt *ast.CommClause) string { 329 | sb := new(strings.Builder) 330 | 331 | if stmt.Comm != nil { 332 | sb.WriteString("case ") 333 | sb.WriteString(m.stringifyStmt(stmt.Comm)) 334 | sb.WriteString(":") 335 | } else { 336 | sb.WriteString("default:") 337 | } 338 | for _, stmt := range stmt.Body { 339 | sb.WriteString(m.stringifyStmt(stmt)) 340 | sb.WriteString(";") 341 | } 342 | 343 | return sb.String() 344 | } 345 | 346 | func (m *mingo) stringifyTypeSwitchStmt(stmt *ast.TypeSwitchStmt) string { 347 | sb := new(strings.Builder) 348 | sb.WriteString("switch ") 349 | if stmt.Init != nil { 350 | sb.WriteString(m.stringifyStmt(stmt.Init)) 351 | sb.WriteString(";") 352 | } 353 | if stmt.Assign != nil { 354 | sb.WriteString(m.stringifyStmt(stmt.Assign)) 355 | } 356 | if stmt.Body != nil { 357 | sb.WriteString(m.stringifyBlockStmt(stmt.Body)) 358 | } 359 | 360 | return sb.String() 361 | } 362 | -------------------------------------------------------------------------------- /internal/mingo/testdata/const/expected: -------------------------------------------------------------------------------- 1 | package main;const(A=1;B int=2;C,D int=3,4;E,F,G=3,4,5);const(_=iota;a;b;c);const w=1;const x int=2;const y,z=3,4;func main(){const a=1;const b,c=2,3;const(d=4;e=5);}; -------------------------------------------------------------------------------- /internal/mingo/testdata/const/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const ( 4 | A = 1 5 | B int = 2 6 | C, D int = 3, 4 7 | E, F, G = 3, 4, 5 8 | ) 9 | 10 | const ( 11 | _ = iota 12 | a 13 | b 14 | c 15 | ) 16 | 17 | const w = 1 18 | const x int = 2 19 | const y, z = 3, 4 20 | 21 | func main() { 22 | const a = 1 23 | const b, c = 2, 3 24 | const ( 25 | d = 4 26 | e = 5 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /internal/mingo/testdata/for/expected: -------------------------------------------------------------------------------- 1 | package main;func main(){for {break};for i:=0;i<10;i++{println(i)};for i:=0;i<10;{println(i);i++};for i:=0;;i++{if i>=10{break};println(i)};i:=0;for ;i<10;i++{println(i)};for i<20{println(i);i++};for true{break}}; -------------------------------------------------------------------------------- /internal/mingo/testdata/for/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | for { 5 | break 6 | } 7 | 8 | for i := 0; i < 10; i++ { 9 | println(i) 10 | } 11 | 12 | for i := 0; i < 10; { 13 | println(i) 14 | i++ 15 | } 16 | 17 | for i := 0; ; i++ { 18 | if i >= 10 { 19 | break 20 | } 21 | println(i) 22 | } 23 | 24 | i := 0 25 | for ; i < 10; i++ { 26 | println(i) 27 | } 28 | 29 | for i < 20 { 30 | println(i) 31 | i++ 32 | } 33 | 34 | for true { 35 | break 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /internal/mingo/testdata/func/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func hello(){func(){fmt.Println("Hello")}();func(s string){fmt.Printf("Hello, %s\n",s)}("world");if err:=func()error{return nil}();err!=nil{fmt.Println(err)}};func main(){go hello()}; -------------------------------------------------------------------------------- /internal/mingo/testdata/func/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func hello() { 6 | func() { 7 | fmt.Println("Hello") 8 | }() 9 | 10 | func(s string) { 11 | fmt.Printf("Hello, %s\n", s) 12 | }("world") 13 | 14 | if err := func() error { 15 | return nil 16 | }(); err != nil { 17 | fmt.Println(err) 18 | } 19 | } 20 | 21 | func main() { 22 | go hello() 23 | } 24 | -------------------------------------------------------------------------------- /internal/mingo/testdata/generic/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func Ptr[T any](p T)*T{return &p};func Equals[T,U comparable](t T,u U)bool{return t==u};func Hoge[T comparable,U fmt.Stringer](s []T,e U)bool{return true};func main(){fmt.Println(Ptr(1))}; -------------------------------------------------------------------------------- /internal/mingo/testdata/generic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func Ptr[T any](p T) *T { 6 | return &p 7 | } 8 | 9 | func Equals[T, U comparable](t T, u U) bool { 10 | return t == u 11 | } 12 | 13 | func Hoge[T comparable, U fmt.Stringer](s []T, e U) bool { 14 | return true 15 | } 16 | 17 | func main() { 18 | fmt.Println(Ptr(1)) 19 | } 20 | -------------------------------------------------------------------------------- /internal/mingo/testdata/go/expected: -------------------------------------------------------------------------------- 1 | package main;import("fmt";"time");func hello(){fmt.Println("Hello, 世界");time.Sleep(1*time.Second)};func main(){go func(){fmt.Println("Hello, 世界");time.Sleep(1*time.Second)}();go hello()}; -------------------------------------------------------------------------------- /internal/mingo/testdata/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func hello() { 9 | fmt.Println("Hello, 世界") 10 | time.Sleep(1 * time.Second) 11 | } 12 | 13 | func main() { 14 | go func() { 15 | fmt.Println("Hello, 世界") 16 | time.Sleep(1 * time.Second) 17 | }() 18 | 19 | go hello() 20 | } 21 | -------------------------------------------------------------------------------- /internal/mingo/testdata/goto/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func main(){fmt.Println("A");goto label;fmt.Println("B");label:fmt.Println("C")}; -------------------------------------------------------------------------------- /internal/mingo/testdata/goto/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("A") 7 | goto label 8 | fmt.Println("B") 9 | label: 10 | fmt.Println("C") 11 | } 12 | -------------------------------------------------------------------------------- /internal/mingo/testdata/if/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func main(){if true{fmt.Println("TRUE");if true{fmt.Println("TRUE")}};if false{fmt.Println("TRUE")}else{fmt.Println("FALSE")};if false{fmt.Println("TRUE")}else if true{fmt.Println("TRUE")};if err:=run1();err!=nil{fmt.Println(err)};if _,err:=run2();err!=nil{fmt.Println(err)}};func run1()error{return nil};func run2()(string,error){return "",nil}; -------------------------------------------------------------------------------- /internal/mingo/testdata/if/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | if true { 7 | fmt.Println("TRUE") 8 | if true { 9 | fmt.Println("TRUE") 10 | } 11 | } 12 | 13 | if false { 14 | fmt.Println("TRUE") 15 | } else { 16 | fmt.Println("FALSE") 17 | } 18 | 19 | if false { 20 | fmt.Println("TRUE") 21 | } else if true { 22 | fmt.Println("TRUE") 23 | } 24 | 25 | if err := run1(); err != nil { 26 | fmt.Println(err) 27 | } 28 | 29 | if _, err := run2(); err != nil { 30 | fmt.Println(err) 31 | } 32 | } 33 | 34 | func run1() error { 35 | return nil 36 | } 37 | 38 | func run2() (string, error) { 39 | return "", nil 40 | } 41 | -------------------------------------------------------------------------------- /internal/mingo/testdata/incdec/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func main(){i:=1;i++;i--;i++;fmt.Println(i)}; -------------------------------------------------------------------------------- /internal/mingo/testdata/incdec/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 1 7 | i++ 8 | i-- 9 | i++ 10 | fmt.Println(i) 11 | } 12 | -------------------------------------------------------------------------------- /internal/mingo/testdata/interface/expected: -------------------------------------------------------------------------------- 1 | package main;type I1 interface{F1()string;F2()(string,error);F3()(s string,err error)};type I2 interface{I1;F4(s string);F5(string);F6(s1,s2 string);F7(s1 string,s2 string);F8(s1,s2 string,i int);F9(f func()string)}; -------------------------------------------------------------------------------- /internal/mingo/testdata/interface/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type I1 interface { 4 | F1() string 5 | F2() (string, error) 6 | F3() (s string, err error) 7 | } 8 | 9 | type I2 interface { 10 | I1 11 | 12 | F4(s string) 13 | F5(string) 14 | F6(s1, s2 string) 15 | F7(s1 string, s2 string) 16 | F8(s1, s2 string, i int) 17 | F9(f func() string) 18 | } 19 | -------------------------------------------------------------------------------- /internal/mingo/testdata/range/expected: -------------------------------------------------------------------------------- 1 | package main;func main(){for range 10{break};for i:=range 10{println(i)};for _,s:=range []string{"a","b","c"}{println(s)};for i,s:=range []string{"a","b","c"}{println(i,s)};for i:=range []string{"a","b","c"}{println(i)}}; -------------------------------------------------------------------------------- /internal/mingo/testdata/range/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | for range 10 { 5 | break 6 | } 7 | 8 | for i := range 10 { 9 | println(i) 10 | } 11 | 12 | for _, s := range []string{"a", "b", "c"} { 13 | println(s) 14 | } 15 | 16 | for i, s := range []string{"a", "b", "c"} { 17 | println(i, s) 18 | } 19 | 20 | for i := range []string{"a", "b", "c"} { 21 | println(i) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /internal/mingo/testdata/slice/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func main(){s:=[]string{"A","B","C"};fmt.Println(s[0]);fmt.Println(s[0:1]);fmt.Println(s[0:]);fmt.Println(s[:1]);fmt.Println(s[:])}; -------------------------------------------------------------------------------- /internal/mingo/testdata/slice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := []string{"A", "B", "C"} 7 | 8 | fmt.Println(s[0]) 9 | fmt.Println(s[0:1]) 10 | fmt.Println(s[0:]) 11 | fmt.Println(s[:1]) 12 | fmt.Println(s[:]) 13 | } 14 | -------------------------------------------------------------------------------- /internal/mingo/testdata/struct/expected: -------------------------------------------------------------------------------- 1 | package main;type S1 struct{S struct{A string;B int;C bool};F1 func()string;F2 func()(string,error);F3 func()(s string,err error)};type S2 struct{S1;A string;B int;C bool;a string;b int;c bool;F4 func(s string);F5 func(string);F6 func(s1,s2 string);F7 func(f1 func()string)};func main(){type S3 struct{S1;A string;B int;C bool};}; -------------------------------------------------------------------------------- /internal/mingo/testdata/struct/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type S1 struct { 4 | S struct { 5 | A string 6 | B int 7 | C bool 8 | } 9 | 10 | F1 func() string 11 | F2 func() (string, error) 12 | F3 func() (s string, err error) 13 | } 14 | 15 | type S2 struct { 16 | S1 17 | 18 | A string 19 | B int 20 | C bool 21 | 22 | a string 23 | b int 24 | c bool 25 | 26 | F4 func(s string) 27 | F5 func(string) 28 | F6 func(s1, s2 string) 29 | F7 func(f1 func() string) 30 | } 31 | 32 | func main() { 33 | type S3 struct { 34 | S1 35 | 36 | A string 37 | B int 38 | C bool 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /internal/mingo/testdata/switch/expected: -------------------------------------------------------------------------------- 1 | package main;import "fmt";func main(){i:=0;switch i{case 0:fmt.Println("1");fmt.Println("2");fmt.Println("3");case 1,2:fmt.Println("4");fmt.Println("5");fmt.Println("6");default:fmt.Println("7");fmt.Println("8");fmt.Println("9")}}; -------------------------------------------------------------------------------- /internal/mingo/testdata/switch/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 0 7 | 8 | switch i { 9 | case 0: 10 | fmt.Println("1") 11 | fmt.Println("2") 12 | fmt.Println("3") 13 | case 1, 2: 14 | fmt.Println("4") 15 | fmt.Println("5") 16 | fmt.Println("6") 17 | default: 18 | fmt.Println("7") 19 | fmt.Println("8") 20 | fmt.Println("9") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /internal/mingo/testdata/var/expected: -------------------------------------------------------------------------------- 1 | package main;var(A=1;B int=2;C,D int=3,4;E,F,G=3,4,5);var w=1;var x int=2;var y,z=3,4;func main(){var a int=1;var b,c int=2,3;var(d=4;e=5);}; -------------------------------------------------------------------------------- /internal/mingo/testdata/var/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var ( 4 | A = 1 5 | B int = 2 6 | C, D int = 3, 4 7 | E, F, G = 3, 4, 5 8 | ) 9 | 10 | var w = 1 11 | var x int = 2 12 | var y, z = 3, 4 13 | 14 | func main() { 15 | var a int = 1 16 | var b, c int = 2, 3 17 | var ( 18 | d = 4 19 | e = 5 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/koki-develop/mingo/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } 10 | --------------------------------------------------------------------------------