Skip to content

mh-cbon/gigo

Repository files navigation

gigo(t)

Cuisse d’agneau, de chevreuil, coupée pour être mangée.

"Un bon gigot d’agneau ."

travis Statusappveyor Status Go Report Card

GoDoc

go generate super charged on steroids

Example

in input it takes

> demo.gigo.go
// +build gigo

package main

type Todo struct {
  Name string
  Done bool
}

type Todos implements<:Mutexed (Slice .Todo "Name")> {
  // it reads as a mutexed list of todo.
}

func (t *Todos) Hello(){fmt.Println("Hello")}

// type Todos implements<Mutexed (Slice .Todo)>
// type Todos implements<.Todo | Slice | Mutexed>
//-
// It should probably be something like this in real apps
// type Todos implements<Slice .Todo>
// type TodosManager struct {Items Todos}
// type MutexedTodosManager implements<Mutexed .TodosManager>


// a template to mutex .
template Mutexed<:.Name> struct {
  lock *sync.Mutex
  // embed the type
  embed <:.Name>
}

// for every method of ., create a new method of Mutexed
<:range $m := .Methods> func (m Mutexed<:$.Name>) <:$m.Name>(<:$m.GetArgsBlock | joinexpr ",">) <:$m.Out> {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.<:$m.GetName>(<:$m.GetArgsNames | joinexpr ",">)
}


// a template to generate a type Slice of .
template <:.Name>Slice struct {
  items []<:.Name>
}

// range over args to produce new FindBy methods
<:range $a := .Args> func (s <:$.Name>Slice) FindBy<:$a>(<:$a> <:$.ArgType $a>) (<:$.Name>,bool) {
  for i, item := range s.items {
    if item.<:$a> == <:$a> {
      return item, true
    }
  }
  return <:$.Name>{}, false
}

// create new Method Push of type .
func (s <:.Name>Slice) Push(item <:.Name>) int {
  s.items = append(s.items, item)
  return len(s.items)
}

func (s <:.Name>Slice) Index(search <:.Name>) int {
  for i, item := range s.items {
    if item == search {
      return i
    }
  }
  return -1
}

func (s <:.Name>Slice) RemoveAt(i index) int {
	s.items = append(s.items[:i], s.items[i+1:]...)
}

func (s <:.Name>Slice) Remove(item <:.Name>) int {
  if i:= s.Index(item); i > -1 {
    s.RemoveAt(i)
    return i
  }
  return -1
}

It produces

$ go run main.go gen demo.gigo.go
// +build gigo

package main

type Todo struct {
  Name string
  Done bool
}
// a template to generate a type Slice of .
type TodoSlice struct {
  items []Todo
}

// range over args to produce new FindBy methods
 func (s TodoSlice) FindByName(Name string) (Todo,bool) {
  for i, item := range s.items {
    if item.Name == Name {
      return item, true
    }
  }
  return Todo{}, false
}

// create new Method Push of type .
func (s TodoSlice) Push(item Todo) int {
  s.items = append(s.items, item)
  return len(s.items)
}


func (s TodoSlice) Index(search Todo) int {
  for i, item := range s.items {
    if item == search {
      return i
    }
  }
  return -1
}


func (s TodoSlice) RemoveAt(i index) int {
	s.items = append(s.items[:i], s.items[i+1:]...)
}


func (s TodoSlice) Remove(item Todo) int {
  if i:= s.Index(item); i > -1 {
    s.RemoveAt(i)
    return i
  }
  return -1
}

// a template to mutex .
type MutexedTodoSlice struct {
  lock *sync.Mutex
  // embed the type
  embed TodoSlice
}

// for every method of ., create a new method of Mutexed
 func (m MutexedTodoSlice) FindByName(Name string)  (Todo,bool) {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.FindByName(Name)
}
 func (m MutexedTodoSlice) Push(item Todo)  int {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.Push(item)
}
 func (m MutexedTodoSlice) Index(search Todo)  int {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.Index(search)
}
 func (m MutexedTodoSlice) RemoveAt(i index)  int {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.RemoveAt(i)
}
 func (m MutexedTodoSlice) Remove(item Todo)  int {
  // lock them all
  lock.Lock()
  defer lock.Unlock()
  // invoke embedded type
  m.embed.Remove(item)
}


type Todos struct {
	MutexedTodoSlice
  // it reads as a mutexed list of todo.
}

func (t *Todos) Hello(){fmt.Println("Hello")}

You can also get a specific symbol

$ go run main.go -symbol Push gen demo.gigo.go
// create new Method Push of type .
func (s TodoSlice) Push(item Todo) int {
  s.items = append(s.items, item)
  return len(s.items)
}

Or you can dump the tokenizer output

$ go run main.go -symbol Push dump demo.gigo.go
-> FuncDecl 11 tokens                    56:0   nlToken              "\n"
                                         57:0   CommentLineToken     "// create new Method Push of type ."
                                         57:35  nlToken              "\n"
                                         58:0   funcToken            "func"
                                         58:4   WsToken              " "
 -> PropsBlockDecl 3 tokens              58:5   parenOpenToken       "("
  -> PropDecl 3 tokens                  
   => IdentifierDecl 1 token             58:6   WordToken            "s"
                                         58:7   WsToken              " "
   -> ExpressionDecl 1 tokens           
    -> IdentifierDecl 2 tokens          
     -> BodyBlockDecl 4 tokens           58:8   TplOpenToken         "<:"
                                         58:10  DotToken             "."
                                         58:11  WordToken            "Name"
     <- BodyBlockDecl                    58:15  TplCloseToken        ">"
    <- IdentifierDecl                    58:16  WordToken            "Slice"
   <- ExpressionDecl 1 tokens           
  <- PropDecl 3 tokens                  
 <- PropsBlockDecl                       58:21  parenCloseToken      ")"
                                         58:22  WsToken              " "
 => IdentifierDecl 1 token               58:23  WordToken            "Push"
 -> PropsBlockDecl 3 tokens              58:27  parenOpenToken       "("
  -> PropDecl 3 tokens                  
   => IdentifierDecl 1 token             58:28  WordToken            "item"
                                         58:32  WsToken              " "
   -> ExpressionDecl 1 tokens           
    -> IdentifierDecl 1 tokens          
     -> BodyBlockDecl 4 tokens           58:33  TplOpenToken         "<:"
                                         58:35  DotToken             "."
                                         58:36  WordToken            "Name"
     <- BodyBlockDecl                    58:40  TplCloseToken        ">"
    <- IdentifierDecl 1 tokens          
   <- ExpressionDecl 1 tokens           
  <- PropDecl 3 tokens                  
 <- PropsBlockDecl                       58:41  parenCloseToken      ")"
 -> PropsBlockDecl 1 tokens             
  -> ExpressionDecl 1 tokens            
   -> IdentifierDecl 2 tokens            58:42  WsToken              " "
   <- IdentifierDecl                     58:43  IntToken             "int"
  <- ExpressionDecl 1 tokens            
 <- PropsBlockDecl 1 tokens             
 -> BodyBlockDecl 11 tokens              58:46  WsToken              " "
                                         58:47  BraceOpenToken       "{"
                                         58:48  nlToken              "\n"
                                         59:0   WsToken              " "
                                         59:1   WsToken              " "
  -> ExpressionDecl 4 tokens            
   -> IdentifierDecl 3 tokens            59:2   WordToken            "s"
                                         59:3   DotToken             "."
   <- IdentifierDecl                     59:4   WordToken            "items"
                                         59:9   WsToken              " "
                                         59:10  assignToken          "="
   -> CallExpr 2 tokens                 
    -> IdentifierDecl 2 tokens           59:11  WsToken              " "
    <- IdentifierDecl                    59:12  WordToken            "append"
    -> CallExprBlock 6 tokens            59:18  parenOpenToken       "("
     -> ExpressionDecl 1 tokens         
      -> IdentifierDecl 3 tokens         59:19  WordToken            "s"
                                         59:20  DotToken             "."
      <- IdentifierDecl                  59:21  WordToken            "items"
     <- ExpressionDecl 1 tokens         
                                         59:26  CommaToken           ","
                                         59:27  WsToken              " "
     -> ExpressionDecl 1 tokens         
      => IdentifierDecl 1 token          59:28  WordToken            "item"
     <- ExpressionDecl 1 tokens         
    <- CallExprBlock                     59:32  parenCloseToken      ")"
   <- CallExpr 2 tokens                 
  <- ExpressionDecl 4 tokens            
                                         59:33  nlToken              "\n"
                                         60:0   WsToken              " "
                                         60:1   WsToken              " "
  -> ReturnDecl 4 tokens                 60:2   returnToken          "return"
                                         60:8   WsToken              " "
   -> ExpressionDecl 1 tokens           
    -> CallExpr 2 tokens                
     => IdentifierDecl 1 token           60:9   WordToken            "len"
     -> CallExprBlock 3 tokens           60:12  parenOpenToken       "("
      -> ExpressionDecl 1 tokens        
       -> IdentifierDecl 3 tokens        60:13  WordToken            "s"
                                         60:14  DotToken             "."
       <- IdentifierDecl                 60:15  WordToken            "items"
      <- ExpressionDecl 1 tokens        
     <- CallExprBlock                    60:20  parenCloseToken      ")"
    <- CallExpr 2 tokens                
   <- ExpressionDecl 1 tokens           
  <- ReturnDecl                          60:21  nlToken              "\n"
 <- BodyBlockDecl                        61:0   BraceCloseToken      "}"
<- FuncDecl 11 tokens

Or get it to string after tokenization

$ go run main.go -symbol Push str demo.gigo.go
// create new Method Push of type .
func (s <:.Name>Slice) Push(item <:.Name>) int {
  s.items = append(s.items, item)
  return len(s.items)
}

Changes

Cli

Added cli features to gen, dump and output results.

Fixed body parsing and printing

Now when a template func is encountered

<:range $m := .Methods> func (m Mutexed<:$.Name>) <:$m.Name>(<:$m.GetArgsBlock | joinexpr ",">) <:$m.Out> {
  lock.Lock()
  defer lock.Unlock()
  m.embed.<:$m.GetName>(<:$m.GetArgsNames | joinexpr ",">)
}

Its body is evaluated, and some helpers have been added to properly display it.

before

 func (m MutexedTodoSlice)  Push((item Todo))  int {
  lock.Lock()
  defer lock.Unlock()
  m.embed. Push((item Todo))
}

after

 func (m MutexedTodoSlice)  Push(item Todo)  int {
  lock.Lock()
  defer lock.Unlock()
  m.embed. Push(item)
}

Added nice error support

package tomate

type tomate struct qsdqd{} // bad
unexpected token
In file=<noname> At=3:19
Found=wordToken wanted=[bracketOpenToken]

...
5  package tomate
6  type tomate struct qsdqd{}
   ---------------------↑
...

Releases

No releases published

Packages

No packages published

Languages