From d2a9c2148bbd6692a82ebc92057ef515a51ebe79 Mon Sep 17 00:00:00 2001 From: Mikhail Knyazhev Date: Wed, 18 Feb 2026 04:03:24 +0300 Subject: [PATCH] refactoring --- LICENSE | 2 +- golang/common_test.go | 58 ++++++ golang/config.go | 14 +- golang/render.go | 72 ++++++- golang/stmt.go | 352 ----------------------------------- golang/stmt_create.go | 64 ------- golang/stmt_test.go | 44 ----- golang/token_basic_types.go | 249 +++++++++++++++++++++++++ golang/token_call.go | 64 +++++++ golang/token_comparison.go | 87 +++++++++ golang/token_determinant.go | 120 ++++++++++++ golang/token_format.go | 42 +++++ golang/token_head.go | 37 ++++ golang/token_operation.go | 37 ++++ golang/tokens.go | 37 ++++ internal/config/config.go | 2 +- internal/gen/render.go | 5 +- internal/gen/types.go | 6 +- internal/models/block.go | 11 +- internal/models/comment.go | 2 +- internal/models/keyword.go | 2 +- internal/models/letter.go | 30 ++- internal/models/operation.go | 4 +- internal/models/text.go | 2 +- types/token.go | 2 +- 25 files changed, 860 insertions(+), 485 deletions(-) create mode 100644 golang/common_test.go delete mode 100644 golang/stmt.go delete mode 100644 golang/stmt_create.go delete mode 100644 golang/stmt_test.go create mode 100644 golang/token_basic_types.go create mode 100644 golang/token_call.go create mode 100644 golang/token_comparison.go create mode 100644 golang/token_determinant.go create mode 100644 golang/token_format.go create mode 100644 golang/token_head.go create mode 100644 golang/token_operation.go create mode 100644 golang/tokens.go diff --git a/LICENSE b/LICENSE index 9c7d996..cd594f8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2025, Mikhail Knyazhev +Copyright (c) 2025-2026, Mikhail Knyazhev Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/golang/common_test.go b/golang/common_test.go new file mode 100644 index 0000000..64e9aa4 --- /dev/null +++ b/golang/common_test.go @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang_test + +import ( + "bytes" + "fmt" + "testing" + + . "go.osspkg.com/gogen/golang" +) + +func Test_newStmt(t *testing.T) { + //SetRawMode() + + buf := bytes.NewBuffer(nil) + + stmt := Comment("Autogenerate code"). + Package("main"). + Import("fmt", "fmt"). + Import("fmt2", "fmt"). + Join( + Func().ID("main").Bracket().Block( + Comment("d"). + Var().ID("a").Op("="). + Map(Interface().Block(), Interface().Block(ID("Do").Bracket().Error())). + Block( + Text("a").Op(":").Text("").Op(","), + Array(2).Int8().Op(":").Raw("1").Op(","), + ). + Comment("d"), + Var().ID("b").Op("=").New(Int8()), + Var().ID("b").Op("=").Make(Slice().Int8(), 0, 10), + Op("*").ID("aaa").Op("=").Append(Op("*").ID("aaa"), Slice().Byte().Op("...")), + For().List(ID("a"), ID("b")).Op(":=").Range().Pkg("fmt").ID("aa").Block(), + For().Block( + Select().Block(), + ), + Switch().ID("aa").Op(".").Bracket(ID("type")).Block( + Case().Slice().Byte().Op(":").Block( + Pkg("fmt").ID("Println").Call(ID("aa")), + ), + Default().Op(":"), + ), + ), + ) + + if err := Render(buf, stmt); err != nil { + t.Fatal(err) + } + + fmt.Println("______________________________") + fmt.Print(buf.String()) + fmt.Println("______________________________") +} diff --git a/golang/config.go b/golang/config.go index 474602e..7072110 100644 --- a/golang/config.go +++ b/golang/config.go @@ -1,15 +1,15 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ package golang import ( - config2 "go.osspkg.com/gogen/internal/config" + cfg "go.osspkg.com/gogen/internal/config" ) -var _ config2.Config = (*config)(nil) +var _ cfg.Config = (*config)(nil) type config struct{} @@ -24,15 +24,15 @@ func (c config) OperationAvailable(op string) bool { } } -func (config) CommentSingle() config2.OpenClose { - return config2.OpenClose{ +func (config) CommentSingle() cfg.OpenClose { + return cfg.OpenClose{ Open: "//", Close: "\n", } } -func (config) CommentMulti() config2.OpenClose { - return config2.OpenClose{ +func (config) CommentMulti() cfg.OpenClose { + return cfg.OpenClose{ Open: "/*\n", Close: "\n*/\n", } diff --git a/golang/render.go b/golang/render.go index 2a8be9a..e86eb74 100644 --- a/golang/render.go +++ b/golang/render.go @@ -1,29 +1,93 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ package golang import ( + "bufio" "bytes" + "fmt" "go/format" "io" + "regexp" + "strconv" + "sync/atomic" "go.osspkg.com/gogen/types" ) +var rawMode = atomic.Bool{} + +func SetRawMode() { + rawMode.Store(true) +} + +func SetDefaultMode() { + rawMode.Store(false) +} + func Render(w io.Writer, arg types.Token) error { buf := bytes.NewBuffer(nil) + if err := arg.Render(buf); err != nil { return err } - b, err := format.Source(buf.Bytes()) - if err != nil { - return err + + var ( + b []byte + err error + ) + + if rawMode.Load() { + b = buf.Bytes() + } else { + if b, err = format.Source(buf.Bytes()); err != nil { + return fmt.Errorf( + "gofmt error: %w%s", + err, getBadCode(buf.Bytes(), err), + ) + } } + if _, err = w.Write(b); err != nil { return err } + return nil } + +var rex = regexp.MustCompile(`(?iU)^(\d+)\:(\d+)\:`) + +func getBadCode(b []byte, err error) string { + if err == nil { + return "" + } + + found := rex.FindStringSubmatch(err.Error()) + if len(found) != 3 { + return "" + } + + line, err := strconv.ParseInt(found[1], 10, 64) + if err != nil { + return "" + } + + scanner := bufio.NewScanner(bytes.NewReader(b)) + var ( + currentLine int64 + code string + ) + + for scanner.Scan() { + if currentLine == line-1 { + code += scanner.Text() + break + } + currentLine++ + } + + return ", code:`" + code + "`" +} diff --git a/golang/stmt.go b/golang/stmt.go deleted file mode 100644 index 481a6c3..0000000 --- a/golang/stmt.go +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package golang - -import ( - "io" - - "go.osspkg.com/gogen/internal/gen" - "go.osspkg.com/gogen/internal/models" - "go.osspkg.com/gogen/types" -) - -type Tokens []types.Token - -func newStmt() *Tokens { - return &Tokens{} -} - -func (v *Tokens) Render(w io.Writer) error { - for _, token := range *v { - if err := gen.Render(w, token); err != nil { - return err - } - } - return nil -} - -func (v *Tokens) Unwrap() []types.Token { - return *v -} - -func (v *Tokens) _add(args ...types.Token) *Tokens { - t := Tokens(args) - *v = append(*v, &t) - return v -} - -func (v *Tokens) Add(args ...types.Token) *Tokens { - *v = append(*v, args...) - return v -} - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) Package(arg string) *Tokens { - return v._add( - &models.Keyword{D: "package"}, - &models.Keyword{D: arg}, - ) -} - -func (v *Tokens) Import(name, module string) *Tokens { - return v._add( - &models.Keyword{D: "import"}, - &models.Keyword{D: name, Verify: true}, - &models.Text{D: module}, - ) -} - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) Func() *Tokens { - *v = append(*v, &models.Keyword{D: "func"}) - return v -} - -func (v *Tokens) Return() *Tokens { - *v = append(*v, &models.Keyword{D: "return"}) - return v -} - -func (v *Tokens) Params(args ...types.Token) *Tokens { - *v = append(*v, &models.Params{D: args, Brace: true}) - return v -} - -func (v *Tokens) List(args ...types.Token) *Tokens { - *v = append(*v, &models.Params{D: args, Brace: false}) - return v -} - -func (v *Tokens) Call(args ...types.Token) *Tokens { - return v.Params(args...) -} - -func (v *Tokens) Block(args ...types.Token) *Tokens { - *v = append(*v, &models.Block{D: args}) - return v -} - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) Comment(arg string) *Tokens { - *v = append(*v, &models.Comment[config]{D: arg}) - return v -} - -func (v *Tokens) Line() *Tokens { - *v = append(*v, &models.Letter{D: "\n"}) - return v -} - -func (v *Tokens) Text(arg string) *Tokens { - *v = append(*v, &models.Text{D: arg}) - return v -} - -func (v *Tokens) Id(arg string) *Tokens { - *v = append(*v, &models.Keyword{D: arg, Verify: true}) - return v -} - -func (v *Tokens) Nil() *Tokens { - *v = append(*v, &models.Keyword{D: "nil"}) - return v -} - -func (v *Tokens) Type() *Tokens { - *v = append(*v, &models.Keyword{D: "type"}) - return v -} - -func (v *Tokens) Var() *Tokens { - *v = append(*v, &models.Keyword{D: "var"}) - return v -} - -func (v *Tokens) Const() *Tokens { - *v = append(*v, &models.Keyword{D: "const"}) - return v -} - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) Op(arg string) *Tokens { - *v = append(*v, &models.Operation[config]{D: arg}) - return v -} - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) If() *Tokens { - *v = append(*v, &models.Keyword{D: "if"}) - return v -} - -func (v *Tokens) Else() *Tokens { - *v = append(*v, &models.Keyword{D: "else"}) - return v -} - -func (v *Tokens) Default() *Tokens { - *v = append(*v, &models.Keyword{D: "default"}) - return v -} - -func (v *Tokens) Fallthrough() *Tokens { - *v = append(*v, &models.Keyword{D: "fallthrough"}) - return v -} - -func (v *Tokens) Break() *Tokens { - *v = append(*v, &models.Keyword{D: "break"}) - return v -} - -func (v *Tokens) Case() *Tokens { - *v = append(*v, &models.Keyword{D: "case"}) - return v -} - -func (v *Tokens) Continue() *Tokens { - *v = append(*v, &models.Keyword{D: "continue"}) - return v -} - -func (v *Tokens) Goto() *Tokens { - *v = append(*v, &models.Keyword{D: "goto"}) - return v -} - -///////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////// - -func (v *Tokens) Struct() *Tokens { - *v = append(*v, &models.Keyword{D: "struct"}) - return v -} - -func (v *Tokens) Interface() *Tokens { - *v = append(*v, &models.Keyword{D: "interface"}) - return v -} - -func (v *Tokens) Any() *Tokens { - *v = append(*v, &models.Keyword{D: "any"}) - return v -} - -func (v *Tokens) Chan() *Tokens { - *v = append(*v, &models.Keyword{D: "chan"}) - return v -} - -func (v *Tokens) Uint8() *Tokens { - *v = append(*v, &models.Keyword{D: "uint8"}) - return v -} - -func (v *Tokens) Uint16() *Tokens { - *v = append(*v, &models.Keyword{D: "uint16"}) - return v -} - -func (v *Tokens) Uint32() *Tokens { - *v = append(*v, &models.Keyword{D: "uint32"}) - return v -} - -func (v *Tokens) Uint64() *Tokens { - *v = append(*v, &models.Keyword{D: "uint64"}) - return v -} - -func (v *Tokens) Int8() *Tokens { - *v = append(*v, &models.Keyword{D: "int8"}) - return v -} - -func (v *Tokens) Int16() *Tokens { - *v = append(*v, &models.Keyword{D: "int16"}) - return v -} - -func (v *Tokens) Int32() *Tokens { - *v = append(*v, &models.Keyword{D: "int32"}) - return v -} - -func (v *Tokens) Int64() *Tokens { - *v = append(*v, &models.Keyword{D: "int64"}) - return v -} - -func (v *Tokens) Float32() *Tokens { - *v = append(*v, &models.Keyword{D: "float32"}) - return v -} - -func (v *Tokens) Float64() *Tokens { - *v = append(*v, &models.Keyword{D: "float64"}) - return v -} - -func (v *Tokens) Complex64() *Tokens { - *v = append(*v, &models.Keyword{D: "complex64"}) - return v -} - -func (v *Tokens) Complex128() *Tokens { - *v = append(*v, &models.Keyword{D: "complex128"}) - return v -} - -func (v *Tokens) Byte() *Tokens { - *v = append(*v, &models.Keyword{D: "byte"}) - return v -} - -func (v *Tokens) Rune() *Tokens { - *v = append(*v, &models.Keyword{D: "rune"}) - return v -} - -func (v *Tokens) Uint() *Tokens { - *v = append(*v, &models.Keyword{D: "uint"}) - return v -} - -func (v *Tokens) Int() *Tokens { - *v = append(*v, &models.Keyword{D: "int"}) - return v -} - -func (v *Tokens) Uintptr() *Tokens { - *v = append(*v, &models.Keyword{D: "uintptr"}) - return v -} - -func (v *Tokens) String() *Tokens { - *v = append(*v, &models.Keyword{D: "string"}) - return v -} - -func (v *Tokens) Bool() *Tokens { - *v = append(*v, &models.Keyword{D: "bool"}) - return v -} - -func (v *Tokens) Error() *Tokens { - *v = append(*v, &models.Keyword{D: "error"}) - return v -} - -///////////////////////////////////////////////////////////////// - -// -//func (v *Tokens) For() *Tokens { -// *v = append(*v, &models.Keyword{D: "for"}) -// return v -//} - -func (v *Tokens) __defer() *Tokens { - *v = append(*v, &models.Keyword{D: "defer"}) - return v -} - -func (v *Tokens) __go() *Tokens { - *v = append(*v, &models.Keyword{D: "go"}) - return v -} - -// -//func (v *Tokens) Map() *Tokens { -// *v = append(*v, &models.Keyword{D: "map"}) -// return v -//} - -// -//func (v *Tokens) Range() *Tokens { -// *v = append(*v, &models.Keyword{D: "range"}) -// return v -//} - -//func (v *Tokens) Select() *Tokens { -// *v = append(*v, &models.Keyword{D: "select"}) -// return v -//} - -//func (v *Tokens) Switch() *Tokens { -// *v = append(*v, &models.Keyword{D: "switch"}) -// return v -//} - -//func (v *Tokens) Array(size int) *Tokens { -// *v = append(*v, &models.Keyword{D: "bool"}) -// return v -//} diff --git a/golang/stmt_create.go b/golang/stmt_create.go deleted file mode 100644 index 759a2eb..0000000 --- a/golang/stmt_create.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package golang - -import "go.osspkg.com/gogen/types" - -func Comment(arg string) *Tokens { - return newStmt().Comment(arg) -} - -func Line() *Tokens { - return newStmt().Line() -} - -func Return() *Tokens { - return newStmt().Return() -} - -func Nil() *Tokens { - return newStmt().Nil() -} - -func Var() *Tokens { - return newStmt().Var() -} - -func Text(arg string) *Tokens { - return newStmt().Text(arg) -} - -func Id(arg string) *Tokens { - return newStmt().Id(arg) -} - -func Package(arg string) *Tokens { - return newStmt().Package(arg) -} - -func Import(name, module string) *Tokens { - return newStmt().Import(name, module) -} - -func Func() *Tokens { - return newStmt().Func() -} - -func Params(args ...types.Token) *Tokens { - return newStmt().Params(args...) -} - -func List(args ...types.Token) *Tokens { - return newStmt().List(args...) -} - -func Defer() *Tokens { - return newStmt().__defer() -} - -func Go() *Tokens { - return newStmt().__go() -} diff --git a/golang/stmt_test.go b/golang/stmt_test.go deleted file mode 100644 index a3fae5f..0000000 --- a/golang/stmt_test.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. - * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. - */ - -package golang_test - -import ( - "bytes" - "fmt" - "testing" - - . "go.osspkg.com/gogen/golang" -) - -func Test_newStmt(t *testing.T) { - buf := bytes.NewBuffer(nil) - - stmt := Comment("Autogenerate code"). - Package("main"). - Add( - Import("fmt", "fmt"). - Import("bytes", "bytes"), - Comment("nolint:errcheck"). - Func().Id("main"). - Params(Id("id").Int64(), Id("name").String()). - Params(Id("err").Error()). - Block( - List(Id("a"), Id("b")).Op(":=").List(Text("123"), Text("321")), - Defer().Func().Params(Id("a").Int()).Block().Call(Id("a")), - Go().Id("A").Call(), - Return().Nil(), - ), - Func().Id("A").Params().Block(), - ) - - if err := Render(buf, stmt); err != nil { - t.Fatal(err) - } - - fmt.Println("______________________________") - fmt.Print(buf.String()) - fmt.Println("______________________________") -} diff --git a/golang/token_basic_types.go b/golang/token_basic_types.go new file mode 100644 index 0000000..2709c8c --- /dev/null +++ b/golang/token_basic_types.go @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "go.osspkg.com/gogen/internal/models" + "go.osspkg.com/gogen/types" +) + +func (v *Tokens) Struct() *Tokens { + *v = append(*v, &models.Keyword{D: "struct"}) + return v +} + +func Struct() *Tokens { + return create().Struct() +} + +func (v *Tokens) Interface() *Tokens { + *v = append(*v, &models.Keyword{D: "interface"}) + return v +} + +func Interface() *Tokens { + return create().Interface() +} + +func (v *Tokens) Any() *Tokens { + *v = append(*v, &models.Keyword{D: "any"}) + return v +} + +func Any() *Tokens { + return create().Any() +} + +func (v *Tokens) Nil() *Tokens { + *v = append(*v, &models.Keyword{D: "nil"}) + return v +} + +func Nil() *Tokens { + return create().Nil() +} + +func (v *Tokens) Chan() *Tokens { + *v = append(*v, &models.Keyword{D: "chan"}) + return v +} + +func Chan() *Tokens { + return create().Chan() +} + +func (v *Tokens) Uint8() *Tokens { + *v = append(*v, &models.Keyword{D: "uint8"}) + return v +} + +func Uint8() *Tokens { + return create().Uint8() +} + +func (v *Tokens) Uint16() *Tokens { + *v = append(*v, &models.Keyword{D: "uint16"}) + return v +} + +func Uint16() *Tokens { + return create().Uint16() +} + +func (v *Tokens) Uint32() *Tokens { + *v = append(*v, &models.Keyword{D: "uint32"}) + return v +} + +func Uint32() *Tokens { + return create().Uint32() +} + +func (v *Tokens) Uint64() *Tokens { + *v = append(*v, &models.Keyword{D: "uint64"}) + return v +} + +func Uint64() *Tokens { + return create().Uint64() +} + +func (v *Tokens) Int8() *Tokens { + *v = append(*v, &models.Keyword{D: "int8"}) + return v +} + +func Int8() *Tokens { + return create().Int8() +} + +func (v *Tokens) Int16() *Tokens { + *v = append(*v, &models.Keyword{D: "int16"}) + return v +} + +func Int16() *Tokens { + return create().Int16() +} + +func (v *Tokens) Int32() *Tokens { + *v = append(*v, &models.Keyword{D: "int32"}) + return v +} + +func Int32() *Tokens { + return create().Int32() +} + +func (v *Tokens) Int64() *Tokens { + *v = append(*v, &models.Keyword{D: "int64"}) + return v +} + +func Int64() *Tokens { + return create().Int64() +} + +func (v *Tokens) Float32() *Tokens { + *v = append(*v, &models.Keyword{D: "float32"}) + return v +} + +func Float32() *Tokens { + return create().Float32() +} + +func (v *Tokens) Float64() *Tokens { + *v = append(*v, &models.Keyword{D: "float64"}) + return v +} + +func Float64() *Tokens { + return create().Float64() +} + +func (v *Tokens) Complex64() *Tokens { + *v = append(*v, &models.Keyword{D: "complex64"}) + return v +} + +func Complex64() *Tokens { + return create().Complex64() +} + +func (v *Tokens) Complex128() *Tokens { + *v = append(*v, &models.Keyword{D: "complex128"}) + return v +} + +func Complex128() *Tokens { + return create().Complex128() +} + +func (v *Tokens) Byte() *Tokens { + *v = append(*v, &models.Keyword{D: "byte"}) + return v +} + +func Byte() *Tokens { + return create().Byte() +} + +func (v *Tokens) Rune() *Tokens { + *v = append(*v, &models.Keyword{D: "rune"}) + return v +} + +func Rune() *Tokens { + return create().Rune() +} + +func (v *Tokens) Uint() *Tokens { + *v = append(*v, &models.Keyword{D: "uint"}) + return v +} + +func Uint() *Tokens { + return create().Uint() +} + +func (v *Tokens) Int() *Tokens { + *v = append(*v, &models.Keyword{D: "int"}) + return v +} + +func Int() *Tokens { + return create().Int() +} + +func (v *Tokens) Uintptr() *Tokens { + *v = append(*v, &models.Keyword{D: "uintptr"}) + return v +} + +func Uintptr() *Tokens { + return create().Uintptr() +} + +func (v *Tokens) String() *Tokens { + *v = append(*v, &models.Keyword{D: "string"}) + return v +} + +func String() *Tokens { + return create().String() +} + +func (v *Tokens) Bool() *Tokens { + *v = append(*v, &models.Keyword{D: "bool"}) + return v +} + +func Bool() *Tokens { + return create().Bool() +} + +func (v *Tokens) Error() *Tokens { + *v = append(*v, &models.Keyword{D: "error"}) + return v +} + +func Error() *Tokens { + return create().Error() +} + +func (v *Tokens) Map(key, val types.Token) *Tokens { + return v.Join( + &models.Raw{D: "map["}, + &models.Raw{T: key}, + &models.Raw{D: "]"}, + &models.Raw{T: val}, + ) +} + +func Map(key, val types.Token) *Tokens { + return create().Map(key, val) +} diff --git a/golang/token_call.go b/golang/token_call.go new file mode 100644 index 0000000..c5d63f9 --- /dev/null +++ b/golang/token_call.go @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "go.osspkg.com/gogen/internal/models" + "go.osspkg.com/gogen/types" +) + +func (v *Tokens) __defer() *Tokens { + *v = append(*v, &models.Keyword{D: "defer"}) + return v +} + +func Defer() *Tokens { + return create().__defer() +} + +func (v *Tokens) __go() *Tokens { + *v = append(*v, &models.Keyword{D: "go"}) + return v +} + +func Go() *Tokens { + return create().__go() +} + +func (v *Tokens) Bracket(args ...types.Token) *Tokens { + *v = append(*v, &models.Bracket{D: args, Brace: true}) + return v +} + +func Params(args ...types.Token) *Tokens { + return create().Bracket(args...) +} + +func (v *Tokens) Call(args ...types.Token) *Tokens { + return v.Bracket(args...) +} + +func Call(args ...types.Token) *Tokens { + return create().Call(args...) +} + +func (v *Tokens) Func() *Tokens { + *v = append(*v, &models.Keyword{D: "func"}) + return v +} + +func Func() *Tokens { + return create().Func() +} + +func (v *Tokens) Return() *Tokens { + *v = append(*v, &models.Keyword{D: "return"}) + return v +} + +func Return() *Tokens { + return create().Return() +} diff --git a/golang/token_comparison.go b/golang/token_comparison.go new file mode 100644 index 0000000..8023fe1 --- /dev/null +++ b/golang/token_comparison.go @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import "go.osspkg.com/gogen/internal/models" + +func (v *Tokens) If() *Tokens { + *v = append(*v, &models.Keyword{D: "if"}) + return v +} + +func If() *Tokens { + return create().If() +} + +func (v *Tokens) Else() *Tokens { + *v = append(*v, &models.Keyword{D: "else"}) + return v +} + +func (v *Tokens) ElseIf() *Tokens { + *v = append(*v, &models.Keyword{D: "else if"}) + return v +} + +func (v *Tokens) Default() *Tokens { + *v = append(*v, &models.Keyword{D: "default"}) + return v +} + +func Default() *Tokens { + return create().Default() +} + +func (v *Tokens) Fallthrough() *Tokens { + *v = append(*v, &models.Keyword{D: "fallthrough"}) + return v +} + +func (v *Tokens) Break() *Tokens { + *v = append(*v, &models.Keyword{D: "break"}) + return v +} + +func (v *Tokens) Case() *Tokens { + *v = append(*v, &models.Keyword{D: "case"}) + return v +} + +func Case() *Tokens { + return create().Case() +} + +func (v *Tokens) Continue() *Tokens { + *v = append(*v, &models.Keyword{D: "continue"}) + return v +} + +func (v *Tokens) Goto() *Tokens { + *v = append(*v, &models.Keyword{D: "goto"}) + return v +} + +func (v *Tokens) For() *Tokens { + *v = append(*v, &models.Keyword{D: "for"}) + return v +} + +func For() *Tokens { + return create().For() +} + +func (v *Tokens) Range() *Tokens { + *v = append(*v, &models.Keyword{D: "range"}) + return v +} + +func Select() *Tokens { + return create().Join(&models.Keyword{D: "select"}) +} + +func Switch() *Tokens { + return create().Join(&models.Keyword{D: "switch"}) +} diff --git a/golang/token_determinant.go b/golang/token_determinant.go new file mode 100644 index 0000000..5451487 --- /dev/null +++ b/golang/token_determinant.go @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "strconv" + + "go.osspkg.com/gogen/internal/models" + "go.osspkg.com/gogen/types" +) + +func (v *Tokens) ID(arg string) *Tokens { + *v = append(*v, &models.Keyword{D: arg, Verify: true}) + return v +} + +func ID(arg string) *Tokens { + return create().ID(arg) +} + +func (v *Tokens) Pkg(arg string) *Tokens { + *v = append(*v, &models.Keyword{D: arg, Verify: true}) + return v.Op(".") +} + +func Pkg(arg string) *Tokens { + return create().Pkg(arg) +} + +func (v *Tokens) Type() *Tokens { + *v = append(*v, &models.Keyword{D: "type"}) + return v +} + +func Type() *Tokens { + return create().Type() +} + +func (v *Tokens) Var() *Tokens { + *v = append(*v, &models.Keyword{D: "var"}) + return v +} + +func Var() *Tokens { + return create().Var() +} + +func (v *Tokens) Const() *Tokens { + *v = append(*v, &models.Keyword{D: "const"}) + return v +} + +func (v *Tokens) List(args ...types.Token) *Tokens { + *v = append(*v, &models.Bracket{D: args, Brace: false}) + return v +} + +func List(args ...types.Token) *Tokens { + return create().List(args...) +} + +func (v *Tokens) Slice() *Tokens { + *v = append(*v, &models.Raw{D: "[]"}) + return v +} + +func Slice() *Tokens { + return create().Slice() +} + +func (v *Tokens) Array(n int) *Tokens { + *v = append(*v, &models.Raw{D: "[" + strconv.Itoa(n) + "]"}) + return v +} + +func Array(n int) *Tokens { + return create().Array(n) +} + +func (v *Tokens) New(arg types.Token) *Tokens { + return v. + Join(&models.Letter{D: "new"}). + Bracket(arg) +} + +func New(arg types.Token) *Tokens { + return create().New(arg) +} + +func (v *Tokens) Make(arg types.Token, len, cap int) *Tokens { + args := make([]types.Token, 0, 3) + args = append(args, arg, &models.Raw{D: strconv.Itoa(len)}) + + if cap > len { + args = append(args, &models.Raw{D: strconv.Itoa(cap)}) + } + + return v.Join(&models.Letter{D: "make"}). + Bracket(args...) +} + +func Make(arg types.Token, len, cap int) *Tokens { + return create().Make(arg, len, cap) +} + +func (v *Tokens) Append(to types.Token, from ...types.Token) *Tokens { + args := make([]types.Token, 0, len(from)+1) + args = append(args, to) + args = append(args, from...) + + return v.Join(&models.Letter{D: "append"}). + Bracket(args...) +} + +func Append(to types.Token, from ...types.Token) *Tokens { + return create().Append(to, from...) +} diff --git a/golang/token_format.go b/golang/token_format.go new file mode 100644 index 0000000..cfaf9de --- /dev/null +++ b/golang/token_format.go @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "go.osspkg.com/gogen/internal/models" + "go.osspkg.com/gogen/types" +) + +func (v *Tokens) Comment(arg string) *Tokens { + *v = append(*v, &models.Comment[config]{D: arg}) + return v +} + +func Comment(arg string) *Tokens { + return create().Comment(arg) +} + +//------------------------------------------------------ + +func (v *Tokens) Line() *Tokens { + *v = append(*v, &models.Letter{D: "\n"}) + return v +} + +func Line() *Tokens { + return create().Line() +} + +//------------------------------------------------------ + +func (v *Tokens) Block(args ...types.Token) *Tokens { + *v = append(*v, &models.Block{D: args}) + return v +} + +func Block(args ...types.Token) *Tokens { + return create().Block(args...) +} diff --git a/golang/token_head.go b/golang/token_head.go new file mode 100644 index 0000000..fd70872 --- /dev/null +++ b/golang/token_head.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import "go.osspkg.com/gogen/internal/models" + +func (v *Tokens) Package(arg string) *Tokens { + return v.Join( + create().Join( + &models.Keyword{D: "package"}, + &models.Keyword{D: arg}, + ), + ) +} + +func Package(arg string) *Tokens { + return create().Package(arg) +} + +//------------------------------------------------------ + +func (v *Tokens) Import(name, module string) *Tokens { + return v.Join( + create().Join( + &models.Keyword{D: "import"}, + &models.Keyword{D: name, Verify: true}, + &models.Text{D: module}, + ), + ) +} + +func Import(name, module string) *Tokens { + return create().Import(name, module) +} diff --git a/golang/token_operation.go b/golang/token_operation.go new file mode 100644 index 0000000..8622402 --- /dev/null +++ b/golang/token_operation.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "go.osspkg.com/gogen/internal/models" +) + +func (v *Tokens) Op(arg string) *Tokens { + *v = append(*v, &models.Operation[config]{D: arg}) + return v +} + +func Op(arg string) *Tokens { + return create().Op(arg) +} + +func (v *Tokens) Raw(arg string) *Tokens { + *v = append(*v, &models.Keyword{D: arg}) + return v +} + +func Raw(arg string) *Tokens { + return create().Raw(arg) +} + +func (v *Tokens) Text(arg string) *Tokens { + *v = append(*v, &models.Text{D: arg}) + return v +} + +func Text(arg string) *Tokens { + return create().Text(arg) +} diff --git a/golang/tokens.go b/golang/tokens.go new file mode 100644 index 0000000..2a6eb95 --- /dev/null +++ b/golang/tokens.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. + * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. + */ + +package golang + +import ( + "io" + + "go.osspkg.com/gogen/internal/gen" + "go.osspkg.com/gogen/types" +) + +type Tokens []types.Token + +func create() *Tokens { + return &Tokens{} +} + +func (v *Tokens) Render(w io.Writer) error { + for _, token := range *v { + if err := gen.Render(w, token); err != nil { + return err + } + } + return nil +} + +func (v *Tokens) Unwrap() []types.Token { + return *v +} + +func (v *Tokens) Join(args ...types.Token) *Tokens { + *v = append(*v, args...) + return v +} diff --git a/internal/config/config.go b/internal/config/config.go index 4e02abd..b791c65 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/gen/render.go b/internal/gen/render.go index ccbe395..babedd7 100644 --- a/internal/gen/render.go +++ b/internal/gen/render.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -53,6 +53,9 @@ func drawList(w io.Writer, list []types.Token, line bool) error { if i >= count { continue } + if _, ok := token.(NoSpace); ok { + continue + } if _, err := io.WriteString(w, " "); err != nil { return err } diff --git a/internal/gen/types.go b/internal/gen/types.go index bcfdbbb..a4b4c2f 100644 --- a/internal/gen/types.go +++ b/internal/gen/types.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -10,3 +10,7 @@ import "go.osspkg.com/gogen/types" type Unwrap interface { Unwrap() []types.Token } + +type NoSpace interface { + NoSpace() +} diff --git a/internal/models/block.go b/internal/models/block.go index cd0a7b2..190fecb 100644 --- a/internal/models/block.go +++ b/internal/models/block.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -18,7 +18,10 @@ type Block struct { func (v *Block) Render(w io.Writer) error { out := make([]any, 0) - out = append(out, "{\n") + out = append(out, "{") + if len(v.D) > 0 { + out = append(out, "\n") + } for _, token := range v.D { out = append(out, token) } @@ -26,12 +29,12 @@ func (v *Block) Render(w io.Writer) error { return gen.Render(w, out...) } -type Params struct { +type Bracket struct { D []types.Token Brace bool } -func (v *Params) Render(w io.Writer) error { +func (v *Bracket) Render(w io.Writer) error { count := len(v.D) - 1 out := make([]any, 0, count*2+2) if v.Brace { diff --git a/internal/models/comment.go b/internal/models/comment.go index 831d62d..e03ba51 100644 --- a/internal/models/comment.go +++ b/internal/models/comment.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/models/keyword.go b/internal/models/keyword.go index 0581c23..4b21c86 100644 --- a/internal/models/keyword.go +++ b/internal/models/keyword.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/models/letter.go b/internal/models/letter.go index ac7e279..1c84a86 100644 --- a/internal/models/letter.go +++ b/internal/models/letter.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -9,6 +9,7 @@ import ( "io" "go.osspkg.com/gogen/internal/gen" + "go.osspkg.com/gogen/types" ) type Letter struct { @@ -18,3 +19,30 @@ type Letter struct { func (v *Letter) Render(w io.Writer) error { return gen.Render(w, v.D) } + +type Raw struct { + D string + T types.Token + AT []types.Token +} + +func (v *Raw) Render(w io.Writer) error { + if err := gen.Render(w, v.D); err != nil { + return err + } + if v.T != nil { + if err := v.T.Render(w); err != nil { + return err + } + } + if len(v.AT) > 0 { + for _, token := range v.AT { + if err := token.Render(w); err != nil { + return err + } + } + } + return nil +} + +func (v *Raw) NoSpace() {} diff --git a/internal/models/operation.go b/internal/models/operation.go index 27d2902..8f652b3 100644 --- a/internal/models/operation.go +++ b/internal/models/operation.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ @@ -24,3 +24,5 @@ func (v *Operation[C]) Render(w io.Writer) error { } return gen.Render(w, v.D) } + +func (v *Operation[C]) NoSpace() {} diff --git a/internal/models/text.go b/internal/models/text.go index 0824c34..7bc1070 100644 --- a/internal/models/text.go +++ b/internal/models/text.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */ diff --git a/types/token.go b/types/token.go index ed10eab..bac87ab 100644 --- a/types/token.go +++ b/types/token.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2025-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file. */