<commit_before>// +build darwin freebsd linux openbsd netbsd dragonfly

package libedit

import (
	"fmt"
	"io"
	"syscall"
	"unsafe"
)

// OSX, NetBSD and OpenBSD bundle libedit, but place headers in
// /usr/include/readline directly.
// FreeBSD bundles libedit, but places headers in /usr/include/edit/readline.
// For Linux we use the bundled sources.

// #cgo darwin openbsd netbsd LDFLAGS: -ledit
// #cgo darwin openbsd netbsd CPPFLAGS: -I/usr/include/readline -Ishim
// #cgo freebsd dragonfly LDFLAGS: -ledit
// #cgo freebsd dragonfly CPPFLAGS: -I/usr/include/edit/readline -Ishim
// #cgo linux LDFLAGS: -lncurses
// #cgo linux CFLAGS: -Wno-unused-result
// #cgo linux CPPFLAGS: -Isrc -Isrc/c-libedit -Isrc/c-libedit/editline -Isrc/c-libedit/linux-build
//
// #include <readline.h>
// #include <stdio.h>
// #include <stdlib.h>
//
// void go_libedit_printstring(char *s) { printf("%s\n", s); }
// extern char **go_libedit_autocomplete(char *word, char *line, int start, int end);
// static char **wrap_autocomplete(const char *word, int start, int end) {
//     return go_libedit_autocomplete((char*)word, rl_line_buffer, start, end);
// }
// rl_completion_func_t *go_libedit_autocomplete_ptr = wrap_autocomplete;
// void go_libedit_set_string_array(char **ar, int p, char *s) { ar[p] = s; }
import "C"

var cAppName *C.char

func Initialize(appname string) error {
	if appname != "" {
		// rl_readline_name allows a user to customize their
		// ~/.editrc configuration per-app.
		cAppName = C.CString(appname)
		C.rl_readline_name = cAppName
	}

	r := C.rl_initialize()
	if r < 0 {
		Cleanup()
		return fmt.Errorf("unable to initialize libedit: %v", syscall.Errno(-r))
	}

	// rl_attempted_completion_function is called pre-completion to generate
	// a set of candidate strings.
	C.rl_attempted_completion_function = C.go_libedit_autocomplete_ptr
	// rl_attempted_completion_over, when non-zero, disables filename completion
	// after the attempted completion function has run.
	C.rl_attempted_completion_over = 1

	return nil
}

var histFile *C.char
var autoSaveHistory = false
var histExpand = true

func UseHistory(file string, autoSave bool, expand bool) error {
	newHistFile := C.CString(file)
	_, err := C.read_history(newHistFile)
	if err != nil && err != syscall.ENOENT {
		C.free(unsafe.Pointer(newHistFile))
		return err
	}

	if histFile != nil {
		C.free(unsafe.Pointer(histFile))
	}
	histFile = newHistFile
	autoSaveHistory = autoSave
	histExpand = expand
	return nil
}

func AddHistory(line string) error {
	cline := C.CString(line)
	defer C.free(unsafe.Pointer(cline))
	C.add_history(cline)
	if autoSaveHistory && histFile != nil {
		_, err := C.write_history(histFile)
		return err
	}
	return nil
}

var cPrompt *C.char

func SetPrompt(prompt string) {
	if cPrompt != nil {
		C.free(unsafe.Pointer(cPrompt))
	}
	cPrompt = C.CString(prompt)
}

func Readline() (string, error) {
	for {
		l, err := C.readline(cPrompt)
		if err != nil {
			if l != nil {
				C.free(unsafe.Pointer(l))
			}
			return "", err
		}
		if l == nil {
			return "", io.EOF
		}

		if histExpand {
			// Process history expansion commands.
			var exp *C.char
			res := C.history_expand(l, &exp)
			C.free(unsafe.Pointer(l))
			if res < 0 {
				// Input to history_expand was not valid; history_expand has
				// printed an error message already, we can just ask for a new
				// line.
				continue
			}
			if res == 2 {
				// History command says print result but do not execute.
				C.go_libedit_printstring(exp)
				C.free(unsafe.Pointer(exp))
				continue
			}
			l = exp
		}

		ret := C.GoString(l)
		C.free(unsafe.Pointer(l))
		return ret, nil
	}
}

func Cleanup() {
	if cPrompt != nil {
		C.free(unsafe.Pointer(cPrompt))
		cPrompt = nil
	}
	if histFile != nil {
		C.free(unsafe.Pointer(histFile))
		histFile = nil
	}
	if cAppName != nil {
		C.free(unsafe.Pointer(cAppName))
		cAppName = nil
	}
}
<commit_msg>Some Darwin/DragonflyBSD compatibility tweaks.<commit_after>// +build darwin freebsd linux openbsd netbsd dragonfly

package libedit

import (
	"fmt"
	"io"
	"syscall"
	"unsafe"
)

// - NetBSD and OpenBSD bundle libedit and place headers in /usr/include/readline.
// - FreeBSD bundles libedit and places headers in /usr/include/edit/readline.
// - OSX bundles libedit and places headers in /usr/include/editline.
// - DragonflyBSD bundles libedit and places headers in /usr/include/priv/readline.
// - Also both DragonflyBSD and OSX uses non-standard typedefs.
// - For Linux we use the bundled sources.

// #cgo openbsd netbsd freebsd dragonfly darwin LDFLAGS: -ledit
// #cgo openbsd netbsd freebsd dragonfly darwin CPPFLAGS: -Ishim
// #cgo openbsd netbsd   CPPFLAGS: -I/usr/include/readline
// #cgo darwin           CPPFLAGS: -I/usr/include/editline
// #cgo freebsd          CPPFLAGS: -I/usr/include/edit/readline
// #cgo dragonfly        CPPFLAGS: -I/usr/include/priv/readline
// #cgo dragonfly darwin CPPFLAGS: -Dweird_completion_typedef
// #cgo linux          LDFLAGS: -lncurses
// #cgo linux          CFLAGS: -Wno-unused-result
// #cgo linux          CPPFLAGS: -Isrc -Isrc/c-libedit -Isrc/c-libedit/editline -Isrc/c-libedit/linux-build
//
// #include <readline.h>
// #include <stdio.h>
// #include <stdlib.h>
//
// // Some helper functions that make the Go code easier on the eye.
// void go_libedit_printstring(char *s) { printf("%s\n", s); }
// void go_libedit_set_string_array(char **ar, int p, char *s) { ar[p] = s; }
//
// // This function is defined in edit_unix_completion.go.
// extern char **go_libedit_autocomplete(char *word, char *line, int start, int end);
//
// // This function adds the const qualifier which the Go //export directive can't generate.
// static char **wrap_autocomplete(const char *word, int start, int end) {
//     return go_libedit_autocomplete((char*)word, rl_line_buffer, start, end);
// }
//
// #ifdef weird_completion_typedef
// #define go_libedit_completion_func_t CPPFunction
// #else
// #define go_libedit_completion_func_t rl_completion_func_t
// #endif
// go_libedit_completion_func_t *go_libedit_autocomplete_ptr = wrap_autocomplete;
import "C"

var cAppName *C.char

func Initialize(appname string) error {
	if appname != "" {
		// rl_readline_name allows a user to customize their
		// ~/.editrc configuration per-app.
		cAppName = C.CString(appname)
		C.rl_readline_name = cAppName
	}

	r := C.rl_initialize()
	if r < 0 {
		Cleanup()
		return fmt.Errorf("unable to initialize libedit: %v", syscall.Errno(-r))
	}

	// rl_attempted_completion_function is called pre-completion to generate
	// a set of candidate strings.
	C.rl_attempted_completion_function = C.go_libedit_autocomplete_ptr
	// rl_attempted_completion_over, when non-zero, disables filename completion
	// after the attempted completion function has run.
	C.rl_attempted_completion_over = 1

	return nil
}

var histFile *C.char
var autoSaveHistory = false
var histExpand = true

func UseHistory(file string, autoSave bool, expand bool) error {
	newHistFile := C.CString(file)
	_, err := C.read_history(newHistFile)
	if err != nil && err != syscall.ENOENT {
		C.free(unsafe.Pointer(newHistFile))
		return err
	}

	if histFile != nil {
		C.free(unsafe.Pointer(histFile))
	}
	histFile = newHistFile
	autoSaveHistory = autoSave
	histExpand = expand
	return nil
}

func AddHistory(line string) error {
	cline := C.CString(line)
	defer C.free(unsafe.Pointer(cline))
	C.add_history(cline)
	if autoSaveHistory && histFile != nil {
		_, err := C.write_history(histFile)
		return err
	}
	return nil
}

var cPrompt *C.char

func SetPrompt(prompt string) {
	if cPrompt != nil {
		C.free(unsafe.Pointer(cPrompt))
	}
	cPrompt = C.CString(prompt)
}

func Readline() (string, error) {
	for {
		l, err := C.readline(cPrompt)
		if err != nil {
			if l != nil {
				C.free(unsafe.Pointer(l))
			}
			return "", err
		}
		if l == nil {
			return "", io.EOF
		}

		if histExpand {
			// Process history expansion commands.
			var exp *C.char
			res := C.history_expand(l, &exp)
			C.free(unsafe.Pointer(l))
			if res < 0 {
				// Input to history_expand was not valid; history_expand has
				// printed an error message already, we can just ask for a new
				// line.
				continue
			}
			if res == 2 {
				// History command says print result but do not execute.
				C.go_libedit_printstring(exp)
				C.free(unsafe.Pointer(exp))
				continue
			}
			l = exp
		}

		ret := C.GoString(l)
		C.free(unsafe.Pointer(l))
		return ret, nil
	}
}

func Cleanup() {
	if cPrompt != nil {
		C.free(unsafe.Pointer(cPrompt))
		cPrompt = nil
	}
	if histFile != nil {
		C.free(unsafe.Pointer(histFile))
		histFile = nil
	}
	if cAppName != nil {
		C.free(unsafe.Pointer(cAppName))
		cAppName = nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/ziutek/emgo/egc/importer"
	"github.com/ziutek/emgo/gotoc"
)

const mainbin = "main.elf"

func egc(ppath string) error {
	srcDir := ""
	if build.IsLocalImport(ppath) {
		var err error
		if srcDir, err = os.Getwd(); err != nil {
			return err
		}
	}
	bp, err := buildCtx.Import(ppath, srcDir, 0)
	if err != nil {
		return err
	}
	return compile(bp)
}

var uptodate = make(map[string]struct{})

var (
	cortexmSizes = &gotoc.StdSizes{4, 8}

	sizesMap = map[string]types.Sizes{
		"cortexm0":  cortexmSizes,
		"cortexm3":  cortexmSizes,
		"cortexm4":  cortexmSizes,
		"cortexm4f": cortexmSizes,
	}
)

func compile(bp *build.Package) error {
	if ok, err := checkPkg(bp); err != nil {
		return err
	} else if ok {
		return nil
	}
	if verbosity > 0 {
		defer fmt.Println(bp.ImportPath)
	}

	// Parse

	flist := make([]*ast.File, 0, len(bp.GoFiles)+1)
	fset := token.NewFileSet()

	for _, fname := range bp.GoFiles {
		fname = filepath.Join(bp.Dir, fname)
		f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
		if err != nil {
			return err
		}
		flist = append(flist, f)
	}

	var iimp string

	ppath := bp.ImportPath
	if bp.Name == "main" {
		ppath = "main"
		iimp = `_ "runtime";_ "builtin"`
	} else if bp.ImportPath != "builtin" {
		iimp = `_ "builtin"`
	}

	f, err := parser.ParseFile(
		fset,
		"_iimports.go",
		"package "+bp.Name+";import("+iimp+")",
		0,
	)
	if err != nil {
		return err
	}
	flist = append(flist, f)

	// Type check

	tc := &types.Config{
		Importer: NewImporter(),
		Sizes:    sizesMap[buildCtx.GOARCH],
	}
	ti := &types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
	}

	pkg, err := tc.Check(ppath, fset, flist, ti)
	if err != nil {
		return err
	}

	// Translate to C

	work := filepath.Join(tmpDir, ppath)
	if err = os.MkdirAll(work, 0700); err != nil {
		return err
	}

	var (
		hpath string
		objs  []string
	)

	if ppath == "main" {
		hpath = filepath.Join(bp.Dir, "_.h")
	} else {
		hpath = filepath.Join(bp.PkgRoot, buildCtx.GOOS+"_"+buildCtx.GOARCH, ppath+".h")
		expath := filepath.Join(work, "__.EXPORTS")
		impath := filepath.Join(work, "__.IMPORTS")
		objs = append(objs, expath, impath, hpath)

		err = os.MkdirAll(filepath.Dir(hpath), 0755)
		if err != nil && !os.IsExist(err) {
			return err
		}
		wp, err := os.Create(expath)
		if err != nil {
			return err
		}
		edata := importer.ExportData(pkg)
		_, err = wp.Write(edata)
		if err != nil {
			return err
		}
		wp.Close()
		wp, err = os.Create(impath)
		if err != nil {
			return err
		}
		for _, p := range pkg.Imports() {
			if _, err := io.WriteString(wp, p.Path()+"\n"); err != nil {
				return err
			}
		}
		wp.Close()
	}

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

	wc, err := os.Create(filepath.Join(bp.Dir, "_.c"))
	if err != nil {
		return err
	}
	defer wc.Close()

	up := strings.Replace(ppath, "/", "$", -1)
	_, err = io.WriteString(wh, "#ifndef "+up+"\n#define "+up+"\n\n")
	if err != nil {
		return err
	}

	gtc := gotoc.NewGTC(fset, pkg, ti, tc.Sizes)
	gtc.SetInlineThres(12)
	gtc.SetBoundsCheck(!disableBC)
	if err = gtc.Translate(wh, wc, flist); err != nil {
		return err
	}

	for _, h := range bp.HFiles {
		if !strings.HasSuffix(h, "+.h") {
			continue
		}
		f, err := os.Open(filepath.Join(bp.Dir, h))
		if err != nil {
			return err
		}
		if _, err = io.WriteString(wh, "\n// included "+h+"\n"); err != nil {
			return err
		}
		if _, err = bufio.NewReader(f).WriteTo(wh); err != nil {
			return err
		}
	}

	if _, err = io.WriteString(wh, "\n#endif\n"); err != nil {
		return err
	}

	var csfiles = []string{"_.c"}

	for _, c := range bp.CFiles {
		if !strings.HasSuffix(c, "+.c") {
			csfiles = append(csfiles, c)
			continue
		}
		f, err := os.Open(filepath.Join(bp.Dir, c))
		if err != nil {
			return err
		}
		if _, err = io.WriteString(wc, "\n// included "+c+"\n"); err != nil {
			return err
		}
		if _, err = bufio.NewReader(f).WriteTo(wc); err != nil {
			return err
		}
	}
	csfiles = append(csfiles, bp.SFiles...)

	// Build (package or binary)

	bt, err := NewBuildTools(&buildCtx)
	if err != nil {
		return err
	}

	if verbosity > 1 {
		bt.Log = os.Stdout
	}

	for _, c := range csfiles {
		// TODO: avoid recompile up to date objects
		o := filepath.Join(work, c[:len(c)-1]+"o")
		c = filepath.Join(bp.Dir, c)
		if err = bt.Compile(o, c); err != nil {
			return err
		}
		objs = append(objs, o)
	}

	if ppath != "main" {
		if err := bt.Archive(hpath[:len(hpath)-1]+"a", objs...); err != nil {
			return err
		}
		now := time.Now()
		return os.Chtimes(hpath, now, now)
	}

	imports := make([]string, len(pkg.Imports()))
	for i, p := range pkg.Imports() {
		imports[i] = p.Path()
	}
	return bt.Link(filepath.Join(bp.Dir, mainbin), imports, objs...)
}

// checkPkg returns true if the package and its dependences are up to date (doesn't
// need to be (re)compiled).
func checkPkg(bp *build.Package) (bool, error) {
	if _, ok := uptodate[bp.ImportPath]; ok {
		return true, nil
	}
	pkgobj := bp.PkgObj
	if bp.Name == "main" {
		pkgobj = filepath.Join(bp.Dir, mainbin)
	}
	oi, err := os.Stat(pkgobj)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	if len(bp.GoFiles) == 0 {
		uptodate[bp.ImportPath] = struct{}{}
		return true, nil
	}
	src := append(bp.GoFiles, bp.CFiles...)
	src = append(src, bp.HFiles...)
	src = append(src, bp.SFiles...)
	dir := filepath.Join(bp.SrcRoot, bp.ImportPath)
	for _, s := range src {
		si, err := os.Stat(filepath.Join(dir, s))
		if err != nil {
			return false, err
		}
		if !oi.ModTime().After(si.ModTime()) {
			return false, nil
		}
	}
	if bp.Name != "main" {
		h := bp.PkgObj[:len(bp.PkgObj)-1] + "h"
		ok, err := checkH(h, oi.ModTime())
		if err != nil {
			return false, err
		}
		if !ok {
			data, err := arReadFile(bp.PkgObj, filepath.Base(h))
			if err != nil {
				return false, err
			}
			if err = ioutil.WriteFile(h, data, 0644); err != nil {
				return false, err
			}
		}
	}
	if bp.ImportPath == "builtin" {
		if len(bp.Imports) > 1 || len(bp.Imports) == 1 && bp.Imports[0] != "unsafe" {
			return false, errors.New("builtin can't import other packages")
		}
	} else {
		imports := addPkg(bp.Imports, "builtin")
		if bp.Name == "main" {
			imports = addPkg(bp.Imports, "runtime")
		}
		for _, imp := range imports {
			if imp == "unsafe" {
				continue
			}
			ibp, err := buildCtx.Import(imp, dir, build.AllowBinary)
			if err != nil {
				return false, err
			}
			if ok, err := checkPkg(ibp); err != nil {
				return false, err
			} else if !ok {
				return false, nil
			} else {
				pi, err := os.Stat(ibp.PkgObj)
				if err != nil {
					return false, err
				}
				if !oi.ModTime().After(pi.ModTime()) {
					return false, nil
				}
			}
			uptodate[imp] = struct{}{}
		}
	}
	uptodate[bp.ImportPath] = struct{}{}
	return true, nil
}

func checkH(h string, omt time.Time) (bool, error) {
	hi, err := os.Stat(h)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	return !omt.Before(hi.ModTime()), nil
}

func addPkg(imports []string, pkg string) []string {
	for _, s := range imports {
		if s == pkg {
			return imports
		}
	}
	return append(imports, pkg)
}
<commit_msg>egc: Use NoinlineThres instead InlineThres<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/ziutek/emgo/egc/importer"
	"github.com/ziutek/emgo/gotoc"
)

const mainbin = "main.elf"

func egc(ppath string) error {
	srcDir := ""
	if build.IsLocalImport(ppath) {
		var err error
		if srcDir, err = os.Getwd(); err != nil {
			return err
		}
	}
	bp, err := buildCtx.Import(ppath, srcDir, 0)
	if err != nil {
		return err
	}
	return compile(bp)
}

var uptodate = make(map[string]struct{})

var (
	cortexmSizes = &gotoc.StdSizes{4, 8}

	sizesMap = map[string]types.Sizes{
		"cortexm0":  cortexmSizes,
		"cortexm3":  cortexmSizes,
		"cortexm4":  cortexmSizes,
		"cortexm4f": cortexmSizes,
	}
)

func compile(bp *build.Package) error {
	if ok, err := checkPkg(bp); err != nil {
		return err
	} else if ok {
		return nil
	}
	if verbosity > 0 {
		defer fmt.Println(bp.ImportPath)
	}

	// Parse

	flist := make([]*ast.File, 0, len(bp.GoFiles)+1)
	fset := token.NewFileSet()

	for _, fname := range bp.GoFiles {
		fname = filepath.Join(bp.Dir, fname)
		f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
		if err != nil {
			return err
		}
		flist = append(flist, f)
	}

	var iimp string

	ppath := bp.ImportPath
	if bp.Name == "main" {
		ppath = "main"
		iimp = `_ "runtime";_ "builtin"`
	} else if bp.ImportPath != "builtin" {
		iimp = `_ "builtin"`
	}

	f, err := parser.ParseFile(
		fset,
		"_iimports.go",
		"package "+bp.Name+";import("+iimp+")",
		0,
	)
	if err != nil {
		return err
	}
	flist = append(flist, f)

	// Type check

	tc := &types.Config{
		Importer: NewImporter(),
		Sizes:    sizesMap[buildCtx.GOARCH],
	}
	ti := &types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
	}

	pkg, err := tc.Check(ppath, fset, flist, ti)
	if err != nil {
		return err
	}

	// Translate to C

	work := filepath.Join(tmpDir, ppath)
	if err = os.MkdirAll(work, 0700); err != nil {
		return err
	}

	var (
		hpath string
		objs  []string
	)

	if ppath == "main" {
		hpath = filepath.Join(bp.Dir, "_.h")
	} else {
		hpath = filepath.Join(bp.PkgRoot, buildCtx.GOOS+"_"+buildCtx.GOARCH, ppath+".h")
		expath := filepath.Join(work, "__.EXPORTS")
		impath := filepath.Join(work, "__.IMPORTS")
		objs = append(objs, expath, impath, hpath)

		err = os.MkdirAll(filepath.Dir(hpath), 0755)
		if err != nil && !os.IsExist(err) {
			return err
		}
		wp, err := os.Create(expath)
		if err != nil {
			return err
		}
		edata := importer.ExportData(pkg)
		_, err = wp.Write(edata)
		if err != nil {
			return err
		}
		wp.Close()
		wp, err = os.Create(impath)
		if err != nil {
			return err
		}
		for _, p := range pkg.Imports() {
			if _, err := io.WriteString(wp, p.Path()+"\n"); err != nil {
				return err
			}
		}
		wp.Close()
	}

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

	wc, err := os.Create(filepath.Join(bp.Dir, "_.c"))
	if err != nil {
		return err
	}
	defer wc.Close()

	up := strings.Replace(ppath, "/", "$", -1)
	_, err = io.WriteString(wh, "#ifndef "+up+"\n#define "+up+"\n\n")
	if err != nil {
		return err
	}

	gtc := gotoc.NewGTC(fset, pkg, ti, tc.Sizes)
	gtc.SetNoinlineThres(13)
	gtc.SetBoundsCheck(!disableBC)
	if err = gtc.Translate(wh, wc, flist); err != nil {
		return err
	}

	for _, h := range bp.HFiles {
		if !strings.HasSuffix(h, "+.h") {
			continue
		}
		f, err := os.Open(filepath.Join(bp.Dir, h))
		if err != nil {
			return err
		}
		if _, err = io.WriteString(wh, "\n// included "+h+"\n"); err != nil {
			return err
		}
		if _, err = bufio.NewReader(f).WriteTo(wh); err != nil {
			return err
		}
	}

	if _, err = io.WriteString(wh, "\n#endif\n"); err != nil {
		return err
	}

	var csfiles = []string{"_.c"}

	for _, c := range bp.CFiles {
		if !strings.HasSuffix(c, "+.c") {
			csfiles = append(csfiles, c)
			continue
		}
		f, err := os.Open(filepath.Join(bp.Dir, c))
		if err != nil {
			return err
		}
		if _, err = io.WriteString(wc, "\n// included "+c+"\n"); err != nil {
			return err
		}
		if _, err = bufio.NewReader(f).WriteTo(wc); err != nil {
			return err
		}
	}
	csfiles = append(csfiles, bp.SFiles...)

	// Build (package or binary)

	bt, err := NewBuildTools(&buildCtx)
	if err != nil {
		return err
	}

	if verbosity > 1 {
		bt.Log = os.Stdout
	}

	for _, c := range csfiles {
		// TODO: avoid recompile up to date objects
		o := filepath.Join(work, c[:len(c)-1]+"o")
		c = filepath.Join(bp.Dir, c)
		if err = bt.Compile(o, c); err != nil {
			return err
		}
		objs = append(objs, o)
	}

	if ppath != "main" {
		if err := bt.Archive(hpath[:len(hpath)-1]+"a", objs...); err != nil {
			return err
		}
		now := time.Now()
		return os.Chtimes(hpath, now, now)
	}

	imports := make([]string, len(pkg.Imports()))
	for i, p := range pkg.Imports() {
		imports[i] = p.Path()
	}
	return bt.Link(filepath.Join(bp.Dir, mainbin), imports, objs...)
}

// checkPkg returns true if the package and its dependences are up to date (doesn't
// need to be (re)compiled).
func checkPkg(bp *build.Package) (bool, error) {
	if _, ok := uptodate[bp.ImportPath]; ok {
		return true, nil
	}
	pkgobj := bp.PkgObj
	if bp.Name == "main" {
		pkgobj = filepath.Join(bp.Dir, mainbin)
	}
	oi, err := os.Stat(pkgobj)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	if len(bp.GoFiles) == 0 {
		uptodate[bp.ImportPath] = struct{}{}
		return true, nil
	}
	src := append(bp.GoFiles, bp.CFiles...)
	src = append(src, bp.HFiles...)
	src = append(src, bp.SFiles...)
	dir := filepath.Join(bp.SrcRoot, bp.ImportPath)
	for _, s := range src {
		si, err := os.Stat(filepath.Join(dir, s))
		if err != nil {
			return false, err
		}
		if !oi.ModTime().After(si.ModTime()) {
			return false, nil
		}
	}
	if bp.Name != "main" {
		h := bp.PkgObj[:len(bp.PkgObj)-1] + "h"
		ok, err := checkH(h, oi.ModTime())
		if err != nil {
			return false, err
		}
		if !ok {
			data, err := arReadFile(bp.PkgObj, filepath.Base(h))
			if err != nil {
				return false, err
			}
			if err = ioutil.WriteFile(h, data, 0644); err != nil {
				return false, err
			}
		}
	}
	if bp.ImportPath == "builtin" {
		if len(bp.Imports) > 1 || len(bp.Imports) == 1 && bp.Imports[0] != "unsafe" {
			return false, errors.New("builtin can't import other packages")
		}
	} else {
		imports := addPkg(bp.Imports, "builtin")
		if bp.Name == "main" {
			imports = addPkg(bp.Imports, "runtime")
		}
		for _, imp := range imports {
			if imp == "unsafe" {
				continue
			}
			ibp, err := buildCtx.Import(imp, dir, build.AllowBinary)
			if err != nil {
				return false, err
			}
			if ok, err := checkPkg(ibp); err != nil {
				return false, err
			} else if !ok {
				return false, nil
			} else {
				pi, err := os.Stat(ibp.PkgObj)
				if err != nil {
					return false, err
				}
				if !oi.ModTime().After(pi.ModTime()) {
					return false, nil
				}
			}
			uptodate[imp] = struct{}{}
		}
	}
	uptodate[bp.ImportPath] = struct{}{}
	return true, nil
}

func checkH(h string, omt time.Time) (bool, error) {
	hi, err := os.Stat(h)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	return !omt.Before(hi.ModTime()), nil
}

func addPkg(imports []string, pkg string) []string {
	for _, s := range imports {
		if s == pkg {
			return imports
		}
	}
	return append(imports, pkg)
}
<|endoftext|>


<commit_before>package unicreds

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
)

// Encrypt AES encryption method which matches the pycrypto package
// using CTR and AES256. Note this routine seeds the counter/iv with a value of 1
// then throws it away?!
func Encrypt(key, plaintext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	ciphertext := make([]byte, len(plaintext))

	initialCounter := newCounter()
	stream := cipher.NewCTR(block, initialCounter)
	stream.XORKeyStream(ciphertext, plaintext)

	return ciphertext, nil
}

// ComputeHmac256 compute a hmac256 signature of the supplied message and return
// the value hex encoded
func ComputeHmac256(message, secret []byte) string {
	h := hmac.New(sha256.New, secret)
	h.Write([]byte(message))
	return hex.EncodeToString(h.Sum(nil))
}

// Decrypt AES encryption method which matches the pycrypto package
// using CTR and AES256. Note this routine seeds the counter/iv with a value of 1
// then throws it away?!
func Decrypt(key, ciphertext []byte) ([]byte, error) {

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	initialCounter := newCounter()

	plaintext := ciphertext

	stream := cipher.NewCTR(block, initialCounter)

	stream.XORKeyStream(plaintext, ciphertext)

	return plaintext, nil
}

// start with a counter block with a default of 1 to be compatible with the python encryptor
// see https://pythonhosted.org/pycrypto/Crypto.Util.Counter-module.html for more info
func newCounter() []byte {
	return []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}
}
<commit_msg>Remove redundant type conversion.<commit_after>package unicreds

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
)

// Encrypt AES encryption method which matches the pycrypto package
// using CTR and AES256. Note this routine seeds the counter/iv with a value of 1
// then throws it away?!
func Encrypt(key, plaintext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	ciphertext := make([]byte, len(plaintext))

	initialCounter := newCounter()
	stream := cipher.NewCTR(block, initialCounter)
	stream.XORKeyStream(ciphertext, plaintext)

	return ciphertext, nil
}

// ComputeHmac256 compute a hmac256 signature of the supplied message and return
// the value hex encoded
func ComputeHmac256(message, secret []byte) string {
	h := hmac.New(sha256.New, secret)
	h.Write(message)
	return hex.EncodeToString(h.Sum(nil))
}

// Decrypt AES encryption method which matches the pycrypto package
// using CTR and AES256. Note this routine seeds the counter/iv with a value of 1
// then throws it away?!
func Decrypt(key, ciphertext []byte) ([]byte, error) {

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	initialCounter := newCounter()

	plaintext := ciphertext

	stream := cipher.NewCTR(block, initialCounter)

	stream.XORKeyStream(plaintext, ciphertext)

	return plaintext, nil
}

// start with a counter block with a default of 1 to be compatible with the python encryptor
// see https://pythonhosted.org/pycrypto/Crypto.Util.Counter-module.html for more info
func newCounter() []byte {
	return []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}
}
<|endoftext|>


<commit_before>package limiter

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
)

// RedisStore is the redis store.
type RedisStore struct {
	Prefix string
	Pool   *redis.Pool
}

// NewRedisStore returns an instance of redis store.
func NewRedisStore(pool *redis.Pool, prefix string) (*RedisStore, error) {
	if prefix == "" {
		prefix = "ratelimit"
	}

	store := &RedisStore{
		Pool:   pool,
		Prefix: prefix,
	}

	if _, err := store.ping(); err != nil {
		return nil, err
	}

	return store, nil
}

// ping checks if redis is alive.
func (s *RedisStore) ping() (bool, error) {
	conn := s.Pool.Get()
	defer conn.Close()

	data, err := conn.Do("PING")
	if err != nil || data == nil {
		return false, err
	}

	return (data == "PONG"), nil
}

// Get returns the limit for the identifier.
func (s *RedisStore) Get(key string, rate Rate) (Context, error) {
	ctx := Context{}
	key = fmt.Sprintf("%s:%s", s.Prefix, key)

	c := s.Pool.Get()
	defer c.Close()
	if err := c.Err(); err != nil {
		return Context{}, err
	}

	expiry := (time.Now().UnixNano()/int64(time.Millisecond) + int64(rate.Period)/int64(time.Millisecond)) / 1000

	exists, err := redis.Bool(c.Do("EXISTS", key))
	if err != nil {
		return ctx, err
	}

	if !exists {
		c.Do("HSET", key, "count", 1)
		c.Do("HSET", key, "reset", expiry)
		c.Do("EXPIRE", key, rate.Period.Seconds())
		return Context{
			Limit:     rate.Limit,
			Remaining: rate.Limit - 1,
			Reset:     expiry,
			Reached:   false,
		}, nil
	}

	count, err := redis.Int64(c.Do("HINCRBY", key, "count", 1))
	if err != nil {
		return ctx, nil
	}

	reset, err := redis.Int64(c.Do("HGET", key, "reset"))
	if err != nil {
		return ctx, nil
	}

	remaining := int64(0)
	if count < rate.Limit {
		remaining = rate.Limit - count
	}

	return Context{
		Limit:     rate.Limit,
		Remaining: remaining,
		Reset:     reset,
		Reached:   count > rate.Limit,
	}, nil
}
<commit_msg>Remove hash.<commit_after>package limiter

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
)

// RedisStore is the redis store.
type RedisStore struct {
	Prefix string
	Pool   *redis.Pool
}

// NewRedisStore returns an instance of redis store.
func NewRedisStore(pool *redis.Pool, prefix string) (*RedisStore, error) {
	if prefix == "" {
		prefix = "ratelimit"
	}

	store := &RedisStore{
		Pool:   pool,
		Prefix: prefix,
	}

	if _, err := store.ping(); err != nil {
		return nil, err
	}

	return store, nil
}

// ping checks if redis is alive.
func (s *RedisStore) ping() (bool, error) {
	conn := s.Pool.Get()
	defer conn.Close()

	data, err := conn.Do("PING")
	if err != nil || data == nil {
		return false, err
	}

	return (data == "PONG"), nil
}

// Get returns the limit for the identifier.
func (s *RedisStore) Get(key string, rate Rate) (Context, error) {
	ctx := Context{}
	key = fmt.Sprintf("%s:%s", s.Prefix, key)

	c := s.Pool.Get()
	defer c.Close()
	if err := c.Err(); err != nil {
		return Context{}, err
	}

	exists, err := redis.Bool(c.Do("EXISTS", key))
	if err != nil {
		return ctx, err
	}

	ms := int64(time.Millisecond)
	if !exists {
		c.Do("SET", key, 1, "EX", rate.Period.Seconds())
		return Context{
			Limit:     rate.Limit,
			Remaining: rate.Limit - 1,
			Reset:     (time.Now().UnixNano()/ms + int64(rate.Period)/ms) / 1000,
			Reached:   false,
		}, nil
	}

	count, err := redis.Int64(c.Do("INCR", key))
	if err != nil {
		return ctx, nil
	}

	pttl, err := redis.Int64(c.Do("PTTL", key))
	if err != nil {
		return ctx, nil
	}

	remaining := int64(0)
	if count < rate.Limit {
		remaining = rate.Limit - count
	}

	return Context{
		Limit:     rate.Limit,
		Remaining: remaining,
		Reset:     time.Now().Add(time.Duration(pttl) * time.Millisecond).Unix(),
		Reached:   count > rate.Limit,
	}, nil
}
<|endoftext|>


<commit_before>package gautomator

import (
	"fmt"
	"github.com/gonum/matrix/mat64" // Matrix
	"io"
	"time"
)

// A task is an action executed by a module
type Task struct {
	Id     int      `json:"id"`
	Origin string   `json:"origin"`
	Name   string   `json:"name"` //the task name
	Node   string   `json:"node"` // The node name
	Module string   `json:"module"`
	Args   []string `json:"args"`
	Status int      `json:"status"` //-2: queued
	// -1: running
	// >=0 : return code
	StartTime      time.Time `json:"startTime"`
	EndTime        time.Time `json:"endTime"`
	TaskCanRunChan chan bool // true: run, false: wait
}

// This is the structure corresponding to the "dot-graph" of a task list
// We store the nodes in a map
// The index is the source node
type TaskGraphStructure struct {
	Tasks           map[int]*Task
	DegreeMatrix    *mat64.Dense
	AdjacencyMatrix *mat64.Dense // Row id is the map id of the source task
	// Col id is the map id of the destination task
}

func (this *TaskGraphStructure) PrintAdjacencyMatrix() {
	rowSize, colSize := this.AdjacencyMatrix.Dims()
	fmt.Printf("  ")
	for c := 0; c < colSize; c++ {
		fmt.Printf("%v ", this.Tasks[c].Name)
	}
	fmt.Printf("\n")
	for r := 0; r < rowSize; r++ {
		fmt.Printf("%v ", this.Tasks[r].Name)
		for c := 0; c < colSize; c++ {
			fmt.Printf("%v ", this.AdjacencyMatrix.At(r, c))
		}
		fmt.Printf("\n")
	}
}

func (this *TaskGraphStructure) PrintDegreeMatrix() {
	rowSize, colSize := this.DegreeMatrix.Dims()
	for r := 0; r < rowSize; r++ {
		for c := 0; c < colSize; c++ {
			fmt.Printf("%v ", this.DegreeMatrix.At(r, c))
		}
		fmt.Printf("\n")
	}
}

func NewTask() *Task {
	return &Task{
		-1,
		"null",
		"null",
		"null",
		"dummy",
		make([]string, 1),
		-2,
		time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
		time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
		make(chan bool),
	}

}
func NewTaskGraphStructure() *TaskGraphStructure {
	return &TaskGraphStructure{
		make(map[int]*Task, 0),
		mat64.NewDense(0, 0, nil),
		mat64.NewDense(0, 0, nil),
	}
}

// Returns a combination of the current structure
// and the one passed as argument
func (this *TaskGraphStructure) AugmentTaskStructure(taskStructure *TaskGraphStructure) *TaskGraphStructure {
	// merging adjacency matrix
	initialRowLen, initialColLen := this.AdjacencyMatrix.Dims()
	addedRowLen, addedColLen := taskStructure.AdjacencyMatrix.Dims()
	this.AdjacencyMatrix = mat64.DenseCopyOf(this.AdjacencyMatrix.Grow(addedRowLen, addedColLen))
	//a, b := this.AdjacencyMatrix.Dims()
	for r := 0; r < initialRowLen+addedRowLen; r++ {
		for c := 0; c < initialColLen+addedColLen; c++ {
			switch {
			case r < initialRowLen && c < initialColLen:
				// If we are in the original matrix: do nothing
			case r < initialRowLen && c > initialColLen:
				// If outside, put some zero
				this.AdjacencyMatrix.Set(r, c, float64(0))
			case r > initialRowLen && c < initialColLen:
				// If outside, put some zero
				this.AdjacencyMatrix.Set(r, c, float64(0))
			case r >= initialRowLen && c >= initialColLen:
				// Add the new matrix
				this.AdjacencyMatrix.Set(r, c, taskStructure.AdjacencyMatrix.At(r-initialRowLen, c-initialColLen))
			}
		}
	}
	// merging degree matrix
	initialRowLen, initialColLen = this.DegreeMatrix.Dims()
	addedRowLen, addedColLen = taskStructure.DegreeMatrix.Dims()
	this.DegreeMatrix = mat64.DenseCopyOf(this.DegreeMatrix.Grow(addedRowLen, addedColLen))
	for r := 0; r < initialRowLen+addedRowLen; r++ {
		for c := 0; c < initialColLen+addedColLen; c++ {
			switch {
			case r < initialRowLen && c < initialColLen:
				// If we are in the original matrix: do nothing
			case r < initialRowLen && c > initialColLen:
				// If outside, set zero
				this.DegreeMatrix.Set(r, c, float64(0))
			case r > initialRowLen && c < initialColLen:
				// If outside, set zero
				this.DegreeMatrix.Set(r, c, float64(0))
			case r >= initialRowLen && c >= initialColLen:
				// Add the new matrix
				this.DegreeMatrix.Set(r, c, taskStructure.DegreeMatrix.At(r-initialRowLen, c-initialColLen))
			}
		}
	}
	actualSize := len(this.Tasks)
	for i, task := range taskStructure.Tasks {
		task.Id = actualSize + i
		this.Tasks[actualSize+i] = task
	}
	return this
}

func (this *TaskGraphStructure) getTaskFromName(name string) (int, *Task) {
	for index, task := range this.Tasks {
		if task.Name == name {
			return index, task
		}
	}
	return -1, nil
}

func colSum(matrix *mat64.Dense, colId int) float64 {
	row, _ := matrix.Dims()
	sum := float64(0)
	for r := 0; r < row; r++ {
		sum += matrix.At(r, colId)
	}
	return sum
}

func rowSum(matrix *mat64.Dense, rowId int) float64 {
	_, col := matrix.Dims()
	sum := float64(0)
	for c := 0; c < col; c++ {
		sum += matrix.At(rowId, c)
	}
	return sum
}

// the aim of this function is to find if a task has a subdefinition (aka an origin) and change it
// Example:
// imagine the graphs
// digraph bla {
//    a -> b;
//    b -> c;
// }
// digraph b {
//    alpha -> gamma;
// }
// then alpha and beta will have "b" as Origin.
// therefore we should add a link in the AdjacencyMatix and in the DegreeMatrix
func (this *TaskGraphStructure) Relink() *TaskGraphStructure {
	// IN this array we store the row,col on which we set 1
	backup := make([]int, 0)
	_, col := this.AdjacencyMatrix.Dims()
	for _, task := range this.Tasks {
		if colSum(this.AdjacencyMatrix, task.Id) == 0 {
			id, _ := this.getTaskFromName(task.Origin)
			if id != -1 {
				// Task is a meta task
				this.Tasks[id].Module = "meta"
				this.AdjacencyMatrix.Set(id, task.Id, float64(1))
				backup = append(backup, id, task.Id)
			}
		}
		if rowSum(this.AdjacencyMatrix, task.Id) == 0 {
			id, _ := this.getTaskFromName(task.Origin)
			if id != -1 {
				for c := 0; c < col; c++ {
					add := true
					for counter := 0; counter < len(backup)-1; counter += 2 {
						if backup[counter] == id && backup[counter+1] == c {
							add = false
						}
					}
					if add == true {
						this.AdjacencyMatrix.Set(task.Id, c, this.AdjacencyMatrix.At(task.Id, c)+this.AdjacencyMatrix.At(id, c))
					}
				}
			}
		}
	}
	//TODO: complete the degreematrix
	return this
}

// Duplicate the task "id"
// Returns the id of the new task and the whole structure
func (this *TaskGraphStructure) DuplicateTask(id int) (int, *TaskGraphStructure) {
	row, _ := this.AdjacencyMatrix.Dims()
	// Add the task to the list
	origin := this.Tasks[id]
	newId := row + 1
	newTask := origin
	newTask.Id = newId
	this.Tasks[newId] = newTask
	// Adjust the AdjacencyMatrix
	this.AdjacencyMatrix = mat64.DenseCopyOf(this.AdjacencyMatrix.Grow(1, 1))
	// Copy the row 'id' to row 'newId'
	for r := 0; r < newId; r++ {
		this.AdjacencyMatrix.Set(r, newId, this.AdjacencyMatrix.At(r, id))
	}
	// Copy the col 'id' to col 'newId'
	for c := 0; c < newId; c++ {
		this.AdjacencyMatrix.Set(newId, c, this.AdjacencyMatrix.At(id, c))
	}
	return newId, this
}

// This function print the dot file associated with the graph
func (this *TaskGraphStructure) PrintDot(w io.Writer) {
	fmt.Fprintln(w, "digraph G {")
	// Writing node definition
	for _, task := range this.Tasks {
		fmt.Fprintf(w, "\t\"%v\" [\n", task.Id)
		fmt.Fprintf(w, "\t\tid = \"%v\"\n", task.Id)
		if task.Module == "meta" {
			fmt.Fprintln(w, "\t\tshape=diamond")
			fmt.Fprintf(w, "\t\tlabel=\"%v\"", task.Name)
		} else {
			fmt.Fprintf(w, "\t\tlabel = \"<name>%v|<node>%v|<module>%v\"\n", task.Name, task.Node, task.Module)
			fmt.Fprintf(w, "\t\tshape = \"record\"\n")
		}
		fmt.Fprintf(w, "\t];\n")
	}
	row, col := this.AdjacencyMatrix.Dims()
	for r := 0; r < row; r++ {
		for c := 0; c < col; c++ {
			if this.AdjacencyMatrix.At(r, c) == 1 {
				fmt.Fprintf(w, "\t%v -> %v\n", this.Tasks[r].Id, this.Tasks[c].Id)
			}
		}
	}
	fmt.Fprintln(w, "}")
}

// Return a structure of all the task with the given origin
func (this *TaskGraphStructure) GetSubstructure(origin string) *TaskGraphStructure {
	subTaskStructure := NewTaskGraphStructure()
	index := 0
	tasksToExtract := make(map[int]*Task, 0)
	for _, task := range this.Tasks {
		if task.Origin == origin {
			//fmt.Printf("Adding %v(%v) at index:%v\n", task.Name, task.Id, index)
			tasksToExtract[index] = task
			index += 1
		}
	}
	// Create the matrix of the correct size
	size := len(tasksToExtract)
	if size > 0 {
		subTaskStructure.AdjacencyMatrix = mat64.NewDense(size, size, nil)
		subTaskStructure.DegreeMatrix = mat64.NewDense(size, size, nil)
		for i := 0; i < size; i++ {
			task := tasksToExtract[i]
			//fmt.Printf("Task with ID:%v and name:%v will have id:%v\n", task.Id, task.Name, i)
			// BUG here probably
			// Construct the AdjacencyMatrix line by line
			for col := 0; col < size; col++ {
				task2 := tasksToExtract[col]
				//fmt.Printf("Setting %v,%v with value from %v,%v\n", i, col, task.Id, task2.Id)
				subTaskStructure.AdjacencyMatrix.Set(i, col, this.AdjacencyMatrix.At(task.Id, task2.Id))
			}
			subTaskStructure.DegreeMatrix.Set(i, i, this.DegreeMatrix.At(task.Id, task.Id))
			subTaskStructure.Tasks[i] = NewTask()
			subTaskStructure.Tasks[i].Name = task.Name
			subTaskStructure.Tasks[i].Module = task.Module
			subTaskStructure.Tasks[i].Args = task.Args
			subTaskStructure.Tasks[i].Origin = task.Origin
			subTaskStructure.Tasks[i].Id = i
		}
		//subTaskStructure.PrintAdjacencyMatrix()
		return subTaskStructure
	} else {
		return nil
	}
}
<commit_msg>Corrected the issue #3 Implented a map instead of the simple []int<commit_after>package gautomator

import (
	"fmt"
	"github.com/gonum/matrix/mat64" // Matrix
	"io"
	"time"
)

// A task is an action executed by a module
type Task struct {
	Id     int      `json:"id"`
	Origin string   `json:"origin"`
	Name   string   `json:"name"` //the task name
	Node   string   `json:"node"` // The node name
	Module string   `json:"module"`
	Args   []string `json:"args"`
	Status int      `json:"status"` //-2: queued
	// -1: running
	// >=0 : return code
	StartTime      time.Time `json:"startTime"`
	EndTime        time.Time `json:"endTime"`
	TaskCanRunChan chan bool // true: run, false: wait
}

// This is the structure corresponding to the "dot-graph" of a task list
// We store the nodes in a map
// The index is the source node
type TaskGraphStructure struct {
	Tasks           map[int]*Task
	DegreeMatrix    *mat64.Dense
	AdjacencyMatrix *mat64.Dense // Row id is the map id of the source task
	// Col id is the map id of the destination task
}

func (this *TaskGraphStructure) PrintAdjacencyMatrix() {
	rowSize, colSize := this.AdjacencyMatrix.Dims()
	fmt.Printf("  ")
	for c := 0; c < colSize; c++ {
		fmt.Printf("%v ", this.Tasks[c].Name)
	}
	fmt.Printf("\n")
	for r := 0; r < rowSize; r++ {
		fmt.Printf("%v ", this.Tasks[r].Name)
		for c := 0; c < colSize; c++ {
			fmt.Printf("%v ", this.AdjacencyMatrix.At(r, c))
		}
		fmt.Printf("\n")
	}
}

func (this *TaskGraphStructure) PrintDegreeMatrix() {
	rowSize, colSize := this.DegreeMatrix.Dims()
	for r := 0; r < rowSize; r++ {
		for c := 0; c < colSize; c++ {
			fmt.Printf("%v ", this.DegreeMatrix.At(r, c))
		}
		fmt.Printf("\n")
	}
}

func NewTask() *Task {
	return &Task{
		-1,
		"null",
		"null",
		"null",
		"dummy",
		make([]string, 1),
		-2,
		time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
		time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
		make(chan bool),
	}

}
func NewTaskGraphStructure() *TaskGraphStructure {
	return &TaskGraphStructure{
		make(map[int]*Task, 0),
		mat64.NewDense(0, 0, nil),
		mat64.NewDense(0, 0, nil),
	}
}

// Returns a combination of the current structure
// and the one passed as argument
func (this *TaskGraphStructure) AugmentTaskStructure(taskStructure *TaskGraphStructure) *TaskGraphStructure {
	// merging adjacency matrix
	initialRowLen, initialColLen := this.AdjacencyMatrix.Dims()
	addedRowLen, addedColLen := taskStructure.AdjacencyMatrix.Dims()
	this.AdjacencyMatrix = mat64.DenseCopyOf(this.AdjacencyMatrix.Grow(addedRowLen, addedColLen))
	//a, b := this.AdjacencyMatrix.Dims()
	for r := 0; r < initialRowLen+addedRowLen; r++ {
		for c := 0; c < initialColLen+addedColLen; c++ {
			switch {
			case r < initialRowLen && c < initialColLen:
				// If we are in the original matrix: do nothing
			case r < initialRowLen && c > initialColLen:
				// If outside, put some zero
				this.AdjacencyMatrix.Set(r, c, float64(0))
			case r > initialRowLen && c < initialColLen:
				// If outside, put some zero
				this.AdjacencyMatrix.Set(r, c, float64(0))
			case r >= initialRowLen && c >= initialColLen:
				// Add the new matrix
				this.AdjacencyMatrix.Set(r, c, taskStructure.AdjacencyMatrix.At(r-initialRowLen, c-initialColLen))
			}
		}
	}
	// merging degree matrix
	initialRowLen, initialColLen = this.DegreeMatrix.Dims()
	addedRowLen, addedColLen = taskStructure.DegreeMatrix.Dims()
	this.DegreeMatrix = mat64.DenseCopyOf(this.DegreeMatrix.Grow(addedRowLen, addedColLen))
	for r := 0; r < initialRowLen+addedRowLen; r++ {
		for c := 0; c < initialColLen+addedColLen; c++ {
			switch {
			case r < initialRowLen && c < initialColLen:
				// If we are in the original matrix: do nothing
			case r < initialRowLen && c > initialColLen:
				// If outside, set zero
				this.DegreeMatrix.Set(r, c, float64(0))
			case r > initialRowLen && c < initialColLen:
				// If outside, set zero
				this.DegreeMatrix.Set(r, c, float64(0))
			case r >= initialRowLen && c >= initialColLen:
				// Add the new matrix
				this.DegreeMatrix.Set(r, c, taskStructure.DegreeMatrix.At(r-initialRowLen, c-initialColLen))
			}
		}
	}
	actualSize := len(this.Tasks)
	for i, task := range taskStructure.Tasks {
		task.Id = actualSize + i
		this.Tasks[actualSize+i] = task
	}
	return this
}

func (this *TaskGraphStructure) getTaskFromName(name string) (int, *Task) {
	for index, task := range this.Tasks {
		if task.Name == name {
			return index, task
		}
	}
	return -1, nil
}

func colSum(matrix *mat64.Dense, colId int) float64 {
	row, _ := matrix.Dims()
	sum := float64(0)
	for r := 0; r < row; r++ {
		sum += matrix.At(r, colId)
	}
	return sum
}

func rowSum(matrix *mat64.Dense, rowId int) float64 {
	_, col := matrix.Dims()
	sum := float64(0)
	for c := 0; c < col; c++ {
		sum += matrix.At(rowId, c)
	}
	return sum
}

// the aim of this function is to find if a task has a subdefinition (aka an origin) and change it
// Example:
// imagine the graphs
// digraph bla {
//    a -> b;
//    b -> c;
// }
// digraph b {
//    alpha -> gamma;
// }
// then alpha and beta will have "b" as Origin.
// therefore we should add a link in the AdjacencyMatix and in the DegreeMatrix
func (this *TaskGraphStructure) Relink() *TaskGraphStructure {
	// IN this array we store the row,col on which we set 1
	backup := make(map[string][]int, 0)
	_, col := this.AdjacencyMatrix.Dims()
	for _, task := range this.Tasks {
		if colSum(this.AdjacencyMatrix, task.Id) == 0 {
			id, _ := this.getTaskFromName(task.Origin)
			if id != -1 {
				// Task is a meta task
				this.Tasks[id].Module = "meta"
				this.AdjacencyMatrix.Set(id, task.Id, float64(1))
				backup[task.Origin] = append(backup[task.Origin], id, task.Id)
			}
		}
		if rowSum(this.AdjacencyMatrix, task.Id) == 0 {
			id, _ := this.getTaskFromName(task.Origin)
			if id != -1 {
				for c := 0; c < col; c++ {
					add := true
					for counter := 0; counter < len(backup[task.Origin])-1; counter += 2 {
						if backup[task.Origin][counter] == id && backup[task.Origin][counter+1] == c {
							add = false
						}
					}
					if add == true {
						this.AdjacencyMatrix.Set(task.Id, c, this.AdjacencyMatrix.At(task.Id, c)+this.AdjacencyMatrix.At(id, c))
					}
				}
			}
		}
	}
	//TODO: complete the degreematrix
	return this
}

// Duplicate the task "id"
// Returns the id of the new task and the whole structure
func (this *TaskGraphStructure) DuplicateTask(id int) (int, *TaskGraphStructure) {
	row, _ := this.AdjacencyMatrix.Dims()
	// Add the task to the list
	origin := this.Tasks[id]
	newId := row + 1
	newTask := origin
	newTask.Id = newId
	this.Tasks[newId] = newTask
	// Adjust the AdjacencyMatrix
	this.AdjacencyMatrix = mat64.DenseCopyOf(this.AdjacencyMatrix.Grow(1, 1))
	// Copy the row 'id' to row 'newId'
	for r := 0; r < newId; r++ {
		this.AdjacencyMatrix.Set(r, newId, this.AdjacencyMatrix.At(r, id))
	}
	// Copy the col 'id' to col 'newId'
	for c := 0; c < newId; c++ {
		this.AdjacencyMatrix.Set(newId, c, this.AdjacencyMatrix.At(id, c))
	}
	return newId, this
}

// This function print the dot file associated with the graph
func (this *TaskGraphStructure) PrintDot(w io.Writer) {
	fmt.Fprintln(w, "digraph G {")
	// Writing node definition
	for _, task := range this.Tasks {
		fmt.Fprintf(w, "\t\"%v\" [\n", task.Id)
		fmt.Fprintf(w, "\t\tid = \"%v\"\n", task.Id)
		if task.Module == "meta" {
			fmt.Fprintln(w, "\t\tshape=diamond")
			fmt.Fprintf(w, "\t\tlabel=\"%v\"", task.Name)
		} else {
			fmt.Fprintf(w, "\t\tlabel = \"<name>%v|<node>%v|<module>%v\"\n", task.Name, task.Node, task.Module)
			fmt.Fprintf(w, "\t\tshape = \"record\"\n")
		}
		fmt.Fprintf(w, "\t];\n")
	}
	row, col := this.AdjacencyMatrix.Dims()
	for r := 0; r < row; r++ {
		for c := 0; c < col; c++ {
			if this.AdjacencyMatrix.At(r, c) == 1 {
				fmt.Fprintf(w, "\t%v -> %v\n", this.Tasks[r].Id, this.Tasks[c].Id)
			}
		}
	}
	fmt.Fprintln(w, "}")
}

// Return a structure of all the task with the given origin
func (this *TaskGraphStructure) GetSubstructure(origin string) *TaskGraphStructure {
	subTaskStructure := NewTaskGraphStructure()
	index := 0
	tasksToExtract := make(map[int]*Task, 0)
	for _, task := range this.Tasks {
		if task.Origin == origin {
			//fmt.Printf("Adding %v(%v) at index:%v\n", task.Name, task.Id, index)
			tasksToExtract[index] = task
			index += 1
		}
	}
	// Create the matrix of the correct size
	size := len(tasksToExtract)
	if size > 0 {
		subTaskStructure.AdjacencyMatrix = mat64.NewDense(size, size, nil)
		subTaskStructure.DegreeMatrix = mat64.NewDense(size, size, nil)
		for i := 0; i < size; i++ {
			task := tasksToExtract[i]
			//fmt.Printf("Task with ID:%v and name:%v will have id:%v\n", task.Id, task.Name, i)
			// BUG here probably
			// Construct the AdjacencyMatrix line by line
			for col := 0; col < size; col++ {
				task2 := tasksToExtract[col]
				//fmt.Printf("Setting %v,%v with value from %v,%v\n", i, col, task.Id, task2.Id)
				subTaskStructure.AdjacencyMatrix.Set(i, col, this.AdjacencyMatrix.At(task.Id, task2.Id))
			}
			subTaskStructure.DegreeMatrix.Set(i, i, this.DegreeMatrix.At(task.Id, task.Id))
			subTaskStructure.Tasks[i] = NewTask()
			subTaskStructure.Tasks[i].Name = task.Name
			subTaskStructure.Tasks[i].Module = task.Module
			subTaskStructure.Tasks[i].Args = task.Args
			subTaskStructure.Tasks[i].Origin = task.Origin
			subTaskStructure.Tasks[i].Id = i
		}
		//subTaskStructure.PrintAdjacencyMatrix()
		return subTaskStructure
	} else {
		return nil
	}
}
<|endoftext|>


<commit_before>package interaction

import (
	"encoding/json"
	"time"

	"github.com/skygeario/skygear-server/pkg/core/skyerr"
)

// Interaction represents an interaction with authenticators/identities, and authentication process.
type Interaction struct {
	Token       string    `json:"token"`
	CreatedAt   time.Time `json:"created_at"`
	ExpireAt    time.Time `json:"expire_at"`
	SessionID   string    `json:"session_id,omitempty"`
	SessionType string    `json:"session_type,omitempty"`
	ClientID    string    `json:"client_id,omitempty"`

	Intent Intent           `json:"-"`
	Error  *skyerr.APIError `json:"error,omitempty"`

	UserID                 string             `json:"user_id"`
	Identity               *IdentityInfo      `json:"identity"`
	PrimaryAuthenticator   *AuthenticatorInfo `json:"primary_authenticator"`
	SecondaryAuthenticator *AuthenticatorInfo `json:"secondary_authenticator"`

	State                map[string]string   `json:"state,omitempty"`
	PendingIdentity      *IdentityInfo       `json:"pending_identity,omitempty"`
	PendingAuthenticator *AuthenticatorInfo  `json:"pending_authenticator,omitempty"`
	NewIdentities        []IdentityInfo      `json:"new_identities,omitempty"`
	NewAuthenticators    []AuthenticatorInfo `json:"new_authenticators,omitempty"`
}

func (i *Interaction) IsNewIdentity(id string) bool {
	for _, identity := range i.NewIdentities {
		if identity.ID == id {
			return true
		}
	}
	return false
}

func (i *Interaction) IsNewAuthenticator(id string) bool {
	for _, authenticator := range i.NewAuthenticators {
		if authenticator.ID == id {
			return true
		}
	}
	return false
}

func (i *Interaction) MarshalJSON() ([]byte, error) {
	type jsonInteraction struct {
		*Interaction
		Intent     Intent     `json:"intent"`
		IntentType IntentType `json:"intent_type"`
	}
	ji := jsonInteraction{
		Interaction: i,
		Intent:      i.Intent,
		IntentType:  i.Intent.Type(),
	}
	return json.Marshal(ji)
}

func (i *Interaction) UnmarshalJSON(data []byte) error {
	type jsonInteraction struct {
		*Interaction
		Intent     json.RawMessage `json:"intent"`
		IntentType IntentType      `json:"intent_type"`
	}
	ji := &jsonInteraction{Interaction: i}
	if err := json.Unmarshal(data, ji); err != nil {
		return err
	}

	i.Intent = NewIntent(ji.IntentType)
	if err := json.Unmarshal(ji.Intent, i.Intent); err != nil {
		return err
	}

	return nil
}
<commit_msg>Fix recursive serialization<commit_after>package interaction

import (
	"encoding/json"
	"time"

	"github.com/skygeario/skygear-server/pkg/core/skyerr"
)

// Interaction represents an interaction with authenticators/identities, and authentication process.
type Interaction struct {
	Token       string    `json:"token"`
	CreatedAt   time.Time `json:"created_at"`
	ExpireAt    time.Time `json:"expire_at"`
	SessionID   string    `json:"session_id,omitempty"`
	SessionType string    `json:"session_type,omitempty"`
	ClientID    string    `json:"client_id,omitempty"`

	Intent Intent           `json:"-"`
	Error  *skyerr.APIError `json:"error,omitempty"`

	UserID                 string             `json:"user_id"`
	Identity               *IdentityInfo      `json:"identity"`
	PrimaryAuthenticator   *AuthenticatorInfo `json:"primary_authenticator"`
	SecondaryAuthenticator *AuthenticatorInfo `json:"secondary_authenticator"`

	State                map[string]string   `json:"state,omitempty"`
	PendingIdentity      *IdentityInfo       `json:"pending_identity,omitempty"`
	PendingAuthenticator *AuthenticatorInfo  `json:"pending_authenticator,omitempty"`
	NewIdentities        []IdentityInfo      `json:"new_identities,omitempty"`
	NewAuthenticators    []AuthenticatorInfo `json:"new_authenticators,omitempty"`
}

func (i *Interaction) IsNewIdentity(id string) bool {
	for _, identity := range i.NewIdentities {
		if identity.ID == id {
			return true
		}
	}
	return false
}

func (i *Interaction) IsNewAuthenticator(id string) bool {
	for _, authenticator := range i.NewAuthenticators {
		if authenticator.ID == id {
			return true
		}
	}
	return false
}

func (i *Interaction) MarshalJSON() ([]byte, error) {
	type interaction Interaction
	type jsonInteraction struct {
		*interaction
		Intent     Intent     `json:"intent"`
		IntentType IntentType `json:"intent_type"`
	}
	ji := jsonInteraction{
		interaction: (*interaction)(i),
		Intent:      i.Intent,
		IntentType:  i.Intent.Type(),
	}
	return json.Marshal(ji)
}

func (i *Interaction) UnmarshalJSON(data []byte) error {
	type interaction Interaction
	type jsonInteraction struct {
		*interaction
		Intent     json.RawMessage `json:"intent"`
		IntentType IntentType      `json:"intent_type"`
	}
	ji := &jsonInteraction{interaction: (*interaction)(i)}
	if err := json.Unmarshal(data, ji); err != nil {
		return err
	}

	i.Intent = NewIntent(ji.IntentType)
	if err := json.Unmarshal(ji.Intent, i.Intent); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package dpt

import (
	"fmt"
	"reflect"
	"testing"
)

func TestDPT_251600(t *testing.T) {
	var buf []byte
	var dst DPT_251600
	sources := []DPT_251600{
		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: true, WhiteValid: true},
		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: false, GreenValid: false, BlueValid: false, WhiteValid: false},

		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: false, GreenValid: true, BlueValid: true, WhiteValid: true},
		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: false, BlueValid: true, WhiteValid: true},
		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: false, WhiteValid: true},
		DPT_251600{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: true, WhiteValid: false},
	}

	for _, src := range sources {
		buf = src.Pack()
		_ = dst.Unpack(buf)

		if !reflect.DeepEqual(src, dst) {
			fmt.Printf("%+v\n", src)
			fmt.Printf("%+v\n", dst)
			t.Errorf("Value \"%s\" after pack/unpack for DPT_251600 differs. Original value was \"%v\"!", dst, src)
		}
	}
}
<commit_msg>DPT_251500 tests fixed<commit_after>package dpt

import (
	"fmt"
	"reflect"
	"testing"
)

func TestDPT_251600(t *testing.T) {
	var buf []byte
	var dst DPT_251600
	sources := []DPT_251600{
		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: true, WhiteValid: true},
		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: false, GreenValid: false, BlueValid: false, WhiteValid: false},

		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: false, GreenValid: true, BlueValid: true, WhiteValid: true},
		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: false, BlueValid: true, WhiteValid: true},
		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: false, WhiteValid: true},
		{Red: 255, Green: 96, Blue: 0, White: 18, RedValid: true, GreenValid: true, BlueValid: true, WhiteValid: false},
	}

	for _, src := range sources {
		buf = src.Pack()
		_ = dst.Unpack(buf)

		if !reflect.DeepEqual(src, dst) {
			fmt.Printf("%+v\n", src)
			fmt.Printf("%+v\n", dst)
			t.Errorf("Value \"%s\" after pack/unpack for DPT_251600 differs. Original value was \"%v\"!", dst, src)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func main() {
	for i := 1; i < 101; i++ {
		switch {
		case i%3 == 0 && i%5 == 0:
			fmt.Println("FizzBuzz")
		case i%3 == 0:
			fmt.Println("Fizz")
		case i%5 == 0:
			fmt.Println("Buzz")
		default:
			fmt.Println(i)
		} // switch
	} // for
} // main
<commit_msg>New version inspired on http://wiki.c2.com/?FizzBuzzTest<commit_after>package main

import (
	"fmt"
	"strconv"
)

func main() {
	var output string

	for i := 1; i < 101; i++ {
		if i%3 == 0 {
			output = "Fizz"
		}

		if i%5 == 0 {
			output += "Buzz"
		}

		if len(output) == 0 {
			output = strconv.Itoa(i)
		}

		fmt.Println(output)

		output = ""

	} // for
} // main
<|endoftext|>


<commit_before>package pythonast

import (
	"fmt"
	"io"
)

type Writer struct {
	out         io.Writer
	indentLevel int
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{out: w}
}

func (w *Writer) WriteModule(m *Module) {
	for _, bodyStmt := range m.Body {
		w.writeStmt(bodyStmt)
		w.newline()
	}
}

func (w *Writer) writeStmts(stmts []Stmt) {
	for i, stmt := range stmts {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(stmt)
	}
}

func (w *Writer) writeStmt(stmt Stmt) {
	switch s := stmt.(type) {
	case *FunctionDef:
		w.functionDef(s)
	case *ClassDef:
		w.classDef(s)
	case *While:
		w.write("while ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
	case *Assign:
		for i, target := range s.Targets {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(target)
		}
		w.write(" = ")
		w.writeExpr(s.Value)
	case *Return:
		if s.Value != nil {
			w.write("return ")
			w.writeExpr(s.Value)
		} else {
			w.write("return")
		}
	case *Pass:
		w.write("pass")
	case *ExprStmt:
		w.writeExpr(s.Value)
	case *If:
		w.write("if ")
		w.writeExpr(s.Test)
		w.write(":")
		w.indent()
		w.writeStmts(s.Body)
		w.dedent()
		if s.Orelse != nil {
			if elif, ok := s.Orelse[0].(*If); ok {
				w.write("el")
				w.writeStmt(elif)
			} else {
				w.write("else:")
				w.indent()
				w.writeStmts(s.Orelse)
				w.dedent()
			}
		}
	case *AugAssign:
		w.augAssign(s)
	case *For:
		w.write("for ")
		w.writeExpr(s.Target)
		w.write(" in ")
		w.writeExpr(s.Iter)
		w.write(":")
		w.indent()
		for i, bodyStmt := range s.Body {
			if i > 0 {
				w.newline()
			}
			w.writeStmt(bodyStmt)
		}
		w.dedent()
	case *Break:
		w.write("break")
	case *Continue:
		w.write("continue")
	case *Delete:
		w.write("del ")
		for i, target := range s.Targets {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(target)
		}
	case *Try:
		w.try(s)
	default:
		panic(fmt.Sprintf("unknown Stmt: %T", stmt))
	}
}

func (w *Writer) try(s *Try) {
	w.write("try:")
	w.indent()
	w.writeStmts(s.Body)
	w.dedent()
	for _, handler := range s.Handlers {
		w.write("except")
		if handler.Typ != nil {
			w.write(" ")
			w.writeExpr(handler.Typ)
			if handler.Name != Identifier("") {
				w.write(" as ")
				w.identifier(handler.Name)
			}
		}
		w.write(":")
		w.indent()
		w.writeStmts(handler.Body)
		w.dedent()
	}
	if len(s.Orelse) > 0 {
		w.write("else:")
		w.indent()
		w.writeStmts(s.Orelse)
		w.dedent()
	}
}

func (w *Writer) augAssign(s *AugAssign) {
	w.writeExpr(s.Target)
	w.write(" ")
	w.writeOp(s.Op)
	w.write("=")
	w.write(" ")
	w.writeExpr(s.Value)
}

func (w *Writer) writeExprPrec(expr Expr, parentPrec int) {
	if expr == nil {
		panic("nil expr")
	}
	prec := expr.Precedence()
	paren := prec < parentPrec
	if paren {
		w.beginParen()
	}
	switch e := expr.(type) {
	case *BinOp:
		w.writeExprPrec(e.Left, prec)
		w.writeOp(e.Op)
		w.writeExprPrec(e.Right, prec)
	case *Name:
		w.identifier(e.Id)
	case *Num:
		w.write(e.N)
	case *Str:
		w.write(e.S)
	case *Compare:
		w.writeExprPrec(e.Left, prec)
		for i := range e.Ops {
			w.writeCmpOp(e.Ops[i])
			w.writeExprPrec(e.Comparators[i], prec)
		}
	case *Tuple:
		for i, elt := range e.Elts {
			if i > 0 {
				w.comma()
			}
			w.writeExprPrec(elt, prec)
		}
	case *Call:
		w.writeExprPrec(e.Func, prec)
		w.beginParen()
		i := 0
		for _, arg := range e.Args {
			if i != 0 {
				w.comma()
			}
			w.writeExprPrec(arg, prec)
			i++
		}
		for _, kw := range e.Keywords {
			if i != 0 {
				w.comma()
			}
			w.identifier(*kw.Arg)
			w.write("=")
			w.writeExprPrec(kw.Value, prec)
			i++
		}
		w.endParen()
	case *Attribute:
		w.writeExprPrec(e.Value, prec)
		w.write(".")
		w.identifier(e.Attr)
	case *NameConstant:
		w.nameConstant(e)
	case *List:
		w.list(e)
	case *Subscript:
		w.writeExprPrec(e.Value, prec)
		w.write("[")
		w.slice(e.Slice)
		w.write("]")
	case *BoolOpExpr:
		w.boolOpExpr(e)
	case *UnaryOpExpr:
		w.unaryOpExpr(e)
	case *ListComp:
		w.listComp(e)
	default:
		panic(fmt.Sprintf("unknown Expr: %T", expr))
	}
	if paren {
		w.endParen()
	}
}

func (w *Writer) listComp(e *ListComp) {
	w.write("[")
	w.writeExpr(e.Elt)
	for _, g := range e.Generators {
		w.write(" for ")
		w.writeExpr(g.Target)
		w.write(" in ")
		w.writeExpr(g.Iter)
		for _, ifExpr := range g.Ifs {
			w.write(" if ")
			w.writeExpr(ifExpr)
		}
	}
	w.write("]")
}

func (w *Writer) boolOpExpr(e *BoolOpExpr) {
	w.writeExprPrec(e.Values[0], e.Precedence())
	switch e.Op {
	case Or:
		w.write(" or ")
	case And:
		w.write(" and ")
	}
	w.writeExprPrec(e.Values[1], e.Precedence())
}

func (w *Writer) unaryOpExpr(e *UnaryOpExpr) {
	switch e.Op {
	case Invert:
		w.write("~")
	case Not:
		w.write("not ")
	case UAdd:
		w.write("+")
	case USub:
		w.write("-")
	}
	w.writeExprPrec(e.Operand, e.Precedence())
}

func (w *Writer) slice(s Slice) {
	switch s := s.(type) {
	case *Index:
		w.writeExpr(s.Value)
	case *RangeSlice:
		if s.Lower != nil {
			w.writeExpr(s.Lower)
		}
		w.write(":")
		if s.Upper != nil {
			w.writeExpr(s.Upper)
		}
	default:
		panic(fmt.Sprintf("unknown Slice: %T", s))
	}
}

func (w *Writer) list(l *List) {
	w.write("[")
	for i, elt := range l.Elts {
		if i > 0 {
			w.comma()
		}
		w.writeExprPrec(elt, l.Precedence())
	}
	w.write("]")
}

func (w *Writer) nameConstant(nc *NameConstant) {
	switch nc.Value {
	case None:
		w.write("None")
	case True:
		w.write("True")
	case False:
		w.write("False")
	default:
		panic(fmt.Sprintf("unknown NameConstant %v", nc.Value))
	}
}

func (w *Writer) writeExpr(expr Expr) {
	w.writeExprPrec(expr, 0)
}

func (w *Writer) writeOp(op Operator) {
	switch op {
	case Add:
		w.write("+")
	case Sub:
		w.write("-")
	case Mult:
		w.write("*")
	case MatMult:
		w.write("@")
	case Div:
		w.write("/")
	case Mod:
		w.write("%")
	case Pow:
		w.write("**")
	case LShift:
		w.write("<<")
	case RShift:
		w.write(">>")
	case BitOr:
		w.write("|")
	case BitXor:
		w.write("^")
	case BitAnd:
		w.write("&")
	case FloorDiv:
		w.write("//")
	}
}

func (w *Writer) writeCmpOp(op CmpOp) {
	switch op {
	case Eq:
		w.write("==")
	case NotEq:
		w.write("!=")
	case Lt:
		w.write("<")
	case LtE:
		w.write("<=")
	case Gt:
		w.write(">")
	case GtE:
		w.write(">=")
	case Is:
		w.write(" is ")
	case IsNot:
		w.write(" is not ")
	case In:
		w.write(" in ")
	case NotIn:
		w.write(" not in ")
	}
}

func (w *Writer) functionDef(s *FunctionDef) {
	w.write("def ")
	w.identifier(s.Name)
	w.beginParen()
	defaultOffset := len(s.Args.Args) - len(s.Args.Defaults)
	for i, arg := range s.Args.Args {
		if i > 0 {
			w.comma()
		}
		w.identifier(arg.Arg)
		if i >= defaultOffset {
			w.write("=")
			w.writeExpr(s.Args.Defaults[i-defaultOffset])
		}
	}
	w.endParen()
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) classDef(s *ClassDef) {
	w.write("class ")
	w.identifier(s.Name)
	if len(s.Bases) > 0 {
		w.beginParen()
		for i, base := range s.Bases {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(base)
		}
		w.endParen()
	}
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) identifier(i Identifier) {
	w.write(string(i))
}

func (w *Writer) comma() {
	w.write(", ")
}

func (w *Writer) beginParen() {
	w.write("(")
}

func (w *Writer) endParen() {
	w.write(")")
}

func (w *Writer) indent() {
	w.indentLevel++
	w.newline()
}

func (w *Writer) newline() {
	w.write("\n")
	for i := 0; i < w.indentLevel; i++ {
		w.write("    ")
	}
}

func (w *Writer) dedent() {
	w.indentLevel--
	w.newline()
}

func (w *Writer) write(s string) {
	w.out.Write([]byte(s))
}
<commit_msg>Extract some methods<commit_after>package pythonast

import (
	"fmt"
	"io"
)

type Writer struct {
	out         io.Writer
	indentLevel int
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{out: w}
}

func (w *Writer) WriteModule(m *Module) {
	for _, bodyStmt := range m.Body {
		w.writeStmt(bodyStmt)
		w.newline()
	}
}

func (w *Writer) writeStmts(stmts []Stmt) {
	for i, stmt := range stmts {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(stmt)
	}
}

func (w *Writer) writeStmt(stmt Stmt) {
	switch s := stmt.(type) {
	case *FunctionDef:
		w.functionDef(s)
	case *ClassDef:
		w.classDef(s)
	case *While:
		w.while(s)
	case *Assign:
		w.assign(s)
	case *Return:
		w.ret(s)
	case *Pass:
		w.write("pass")
	case *ExprStmt:
		w.writeExpr(s.Value)
	case *If:
		w.ifStmt(s)
	case *AugAssign:
		w.augAssign(s)
	case *For:
		w.forLoop(s)
	case *Break:
		w.write("break")
	case *Continue:
		w.write("continue")
	case *Delete:
		w.del(s)
	case *Try:
		w.try(s)
	default:
		panic(fmt.Sprintf("unknown Stmt: %T", stmt))
	}
}

func (w *Writer) ret(s *Return) {
	if s.Value != nil {
		w.write("return ")
		w.writeExpr(s.Value)
	} else {
		w.write("return")
	}
}

func (w *Writer) del(s *Delete) {
	w.write("del ")
	for i, target := range s.Targets {
		if i > 0 {
			w.comma()
		}
		w.writeExpr(target)
	}
}

func (w *Writer) assign(s *Assign) {
	for i, target := range s.Targets {
		if i > 0 {
			w.comma()
		}
		w.writeExpr(target)
	}
	w.write(" = ")
	w.writeExpr(s.Value)
}

func (w *Writer) while(s *While) {
	w.write("while ")
	w.writeExpr(s.Test)
	w.write(":")
	w.indent()
	w.writeStmts(s.Body)
	w.dedent()
}

func (w *Writer) ifStmt(s *If) {
	w.write("if ")
	w.writeExpr(s.Test)
	w.write(":")
	w.indent()
	w.writeStmts(s.Body)
	w.dedent()
	if s.Orelse != nil {
		if elif, ok := s.Orelse[0].(*If); ok {
			w.write("el")
			w.writeStmt(elif)
		} else {
			w.write("else:")
			w.indent()
			w.writeStmts(s.Orelse)
			w.dedent()
		}
	}
}

func (w *Writer) forLoop(s *For) {
	w.write("for ")
	w.writeExpr(s.Target)
	w.write(" in ")
	w.writeExpr(s.Iter)
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) try(s *Try) {
	w.write("try:")
	w.indent()
	w.writeStmts(s.Body)
	w.dedent()
	for _, handler := range s.Handlers {
		w.write("except")
		if handler.Typ != nil {
			w.write(" ")
			w.writeExpr(handler.Typ)
			if handler.Name != Identifier("") {
				w.write(" as ")
				w.identifier(handler.Name)
			}
		}
		w.write(":")
		w.indent()
		w.writeStmts(handler.Body)
		w.dedent()
	}
	if len(s.Orelse) > 0 {
		w.write("else:")
		w.indent()
		w.writeStmts(s.Orelse)
		w.dedent()
	}
}

func (w *Writer) augAssign(s *AugAssign) {
	w.writeExpr(s.Target)
	w.write(" ")
	w.writeOp(s.Op)
	w.write("=")
	w.write(" ")
	w.writeExpr(s.Value)
}

func (w *Writer) writeExprPrec(expr Expr, parentPrec int) {
	if expr == nil {
		panic("nil expr")
	}
	prec := expr.Precedence()
	paren := prec < parentPrec
	if paren {
		w.beginParen()
	}
	switch e := expr.(type) {
	case *BinOp:
		w.writeExprPrec(e.Left, prec)
		w.writeOp(e.Op)
		w.writeExprPrec(e.Right, prec)
	case *Name:
		w.identifier(e.Id)
	case *Num:
		w.write(e.N)
	case *Str:
		w.write(e.S)
	case *Compare:
		w.writeExprPrec(e.Left, prec)
		for i := range e.Ops {
			w.writeCmpOp(e.Ops[i])
			w.writeExprPrec(e.Comparators[i], prec)
		}
	case *Tuple:
		for i, elt := range e.Elts {
			if i > 0 {
				w.comma()
			}
			w.writeExprPrec(elt, prec)
		}
	case *Call:
		w.writeExprPrec(e.Func, prec)
		w.beginParen()
		i := 0
		for _, arg := range e.Args {
			if i != 0 {
				w.comma()
			}
			w.writeExprPrec(arg, prec)
			i++
		}
		for _, kw := range e.Keywords {
			if i != 0 {
				w.comma()
			}
			w.identifier(*kw.Arg)
			w.write("=")
			w.writeExprPrec(kw.Value, prec)
			i++
		}
		w.endParen()
	case *Attribute:
		w.writeExprPrec(e.Value, prec)
		w.write(".")
		w.identifier(e.Attr)
	case *NameConstant:
		w.nameConstant(e)
	case *List:
		w.list(e)
	case *Subscript:
		w.writeExprPrec(e.Value, prec)
		w.write("[")
		w.slice(e.Slice)
		w.write("]")
	case *BoolOpExpr:
		w.boolOpExpr(e)
	case *UnaryOpExpr:
		w.unaryOpExpr(e)
	case *ListComp:
		w.listComp(e)
	default:
		panic(fmt.Sprintf("unknown Expr: %T", expr))
	}
	if paren {
		w.endParen()
	}
}

func (w *Writer) listComp(e *ListComp) {
	w.write("[")
	w.writeExpr(e.Elt)
	for _, g := range e.Generators {
		w.write(" for ")
		w.writeExpr(g.Target)
		w.write(" in ")
		w.writeExpr(g.Iter)
		for _, ifExpr := range g.Ifs {
			w.write(" if ")
			w.writeExpr(ifExpr)
		}
	}
	w.write("]")
}

func (w *Writer) boolOpExpr(e *BoolOpExpr) {
	w.writeExprPrec(e.Values[0], e.Precedence())
	switch e.Op {
	case Or:
		w.write(" or ")
	case And:
		w.write(" and ")
	}
	w.writeExprPrec(e.Values[1], e.Precedence())
}

func (w *Writer) unaryOpExpr(e *UnaryOpExpr) {
	switch e.Op {
	case Invert:
		w.write("~")
	case Not:
		w.write("not ")
	case UAdd:
		w.write("+")
	case USub:
		w.write("-")
	}
	w.writeExprPrec(e.Operand, e.Precedence())
}

func (w *Writer) slice(s Slice) {
	switch s := s.(type) {
	case *Index:
		w.writeExpr(s.Value)
	case *RangeSlice:
		if s.Lower != nil {
			w.writeExpr(s.Lower)
		}
		w.write(":")
		if s.Upper != nil {
			w.writeExpr(s.Upper)
		}
	default:
		panic(fmt.Sprintf("unknown Slice: %T", s))
	}
}

func (w *Writer) list(l *List) {
	w.write("[")
	for i, elt := range l.Elts {
		if i > 0 {
			w.comma()
		}
		w.writeExprPrec(elt, l.Precedence())
	}
	w.write("]")
}

func (w *Writer) nameConstant(nc *NameConstant) {
	switch nc.Value {
	case None:
		w.write("None")
	case True:
		w.write("True")
	case False:
		w.write("False")
	default:
		panic(fmt.Sprintf("unknown NameConstant %v", nc.Value))
	}
}

func (w *Writer) writeExpr(expr Expr) {
	w.writeExprPrec(expr, 0)
}

func (w *Writer) writeOp(op Operator) {
	switch op {
	case Add:
		w.write("+")
	case Sub:
		w.write("-")
	case Mult:
		w.write("*")
	case MatMult:
		w.write("@")
	case Div:
		w.write("/")
	case Mod:
		w.write("%")
	case Pow:
		w.write("**")
	case LShift:
		w.write("<<")
	case RShift:
		w.write(">>")
	case BitOr:
		w.write("|")
	case BitXor:
		w.write("^")
	case BitAnd:
		w.write("&")
	case FloorDiv:
		w.write("//")
	}
}

func (w *Writer) writeCmpOp(op CmpOp) {
	switch op {
	case Eq:
		w.write("==")
	case NotEq:
		w.write("!=")
	case Lt:
		w.write("<")
	case LtE:
		w.write("<=")
	case Gt:
		w.write(">")
	case GtE:
		w.write(">=")
	case Is:
		w.write(" is ")
	case IsNot:
		w.write(" is not ")
	case In:
		w.write(" in ")
	case NotIn:
		w.write(" not in ")
	}
}

func (w *Writer) functionDef(s *FunctionDef) {
	w.write("def ")
	w.identifier(s.Name)
	w.beginParen()
	defaultOffset := len(s.Args.Args) - len(s.Args.Defaults)
	for i, arg := range s.Args.Args {
		if i > 0 {
			w.comma()
		}
		w.identifier(arg.Arg)
		if i >= defaultOffset {
			w.write("=")
			w.writeExpr(s.Args.Defaults[i-defaultOffset])
		}
	}
	w.endParen()
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) classDef(s *ClassDef) {
	w.write("class ")
	w.identifier(s.Name)
	if len(s.Bases) > 0 {
		w.beginParen()
		for i, base := range s.Bases {
			if i > 0 {
				w.comma()
			}
			w.writeExpr(base)
		}
		w.endParen()
	}
	w.write(":")
	w.indent()
	for i, bodyStmt := range s.Body {
		if i > 0 {
			w.newline()
		}
		w.writeStmt(bodyStmt)
	}
	w.dedent()
}

func (w *Writer) identifier(i Identifier) {
	w.write(string(i))
}

func (w *Writer) comma() {
	w.write(", ")
}

func (w *Writer) beginParen() {
	w.write("(")
}

func (w *Writer) endParen() {
	w.write(")")
}

func (w *Writer) indent() {
	w.indentLevel++
	w.newline()
}

func (w *Writer) newline() {
	w.write("\n")
	for i := 0; i < w.indentLevel; i++ {
		w.write("    ")
	}
}

func (w *Writer) dedent() {
	w.indentLevel--
	w.newline()
}

func (w *Writer) write(s string) {
	w.out.Write([]byte(s))
}
<|endoftext|>


<commit_before>package queryset

import (
	"fmt"
	"log"
	"strings"
	"unicode"

	"github.com/jinzhu/gorm"
)

type method interface {
	GetMethodName() string
	GetArgsDeclaration() string
	GetBody() string
}

// baseMethod

type baseMethod struct {
	name string
}

func newBaseMethod(name string) baseMethod {
	return baseMethod{
		name: name,
	}
}

// GetMethodName returns name of method
func (m baseMethod) GetMethodName() string {
	return m.name
}

func (m baseMethod) wrapMethod(code string) string {
	const tmpl = `qs.db = qs.db.Scopes(func(d *gorm.DB) *gorm.DB {
      %s})
    return qs`
	return fmt.Sprintf(tmpl, code)
}

// onFieldMethod

type onFieldMethod struct {
	baseMethod
	fieldName        string
	isFieldNameFirst bool
}

func (m *onFieldMethod) setFieldNameFirst(isFieldNameFirst bool) {
	m.isFieldNameFirst = isFieldNameFirst
}

// GetMethodName returns name of method
func (m onFieldMethod) GetMethodName() string {
	args := []string{m.fieldName, strings.Title(m.name)}
	if !m.isFieldNameFirst {
		args[0], args[1] = args[1], args[0]
	}
	return args[0] + args[1]
}

func newOnFieldMethod(name, fieldName string) onFieldMethod {
	return onFieldMethod{
		baseMethod:       newBaseMethod(name),
		fieldName:        fieldName,
		isFieldNameFirst: true,
	}
}

// oneArgMethod

type oneArgMethod struct {
	argName     string
	argTypeName string
}

func (m oneArgMethod) getArgName() string {
	return m.argName
}

// GetArgsDeclaration returns declaration of arguments list for func decl
func (m oneArgMethod) GetArgsDeclaration() string {
	return fmt.Sprintf("%s %s", m.getArgName(), m.argTypeName)
}

func newOneArgMethod(argName, argTypeName string) oneArgMethod {
	return oneArgMethod{
		argName:     argName,
		argTypeName: argTypeName,
	}
}

// noArgsMethod

type noArgsMethod struct{}

// GetArgsDeclaration returns declaration of arguments list for func decl
func (m noArgsMethod) GetArgsDeclaration() string {
	return ""
}

// fieldOperationNoArgsMethod

// fieldOperationNoArgsMethod is for unary operations: preload, orderby, etc
type fieldOperationNoArgsMethod struct {
	onFieldMethod
	noArgsMethod
	gormMethodName string
}

func (m *fieldOperationNoArgsMethod) setGormMethodName(name string) {
	m.gormMethodName = name
}

// GetBody returns method body
func (m fieldOperationNoArgsMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s("%s")`, m.gormMethodName, m.fieldName))
}

func newFieldOperationNoArgsMethod(name, fieldName string) fieldOperationNoArgsMethod {
	r := fieldOperationNoArgsMethod{
		onFieldMethod:  newOnFieldMethod(name, fieldName),
		gormMethodName: name,
	}
	r.setFieldNameFirst(false) // UserPreload -> PreloadUser
	return r
}

// fieldOperationOneArgMethod

type fieldOperationOneArgMethod struct {
	onFieldMethod
	oneArgMethod
}

// GetBody returns method body
func (m fieldOperationOneArgMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s(%s)`, m.name, m.getArgName()))
}

func lowercaseFirstRune(s string) string {
	r := []rune(s)
	r[0] = unicode.ToLower(r[0])
	return string(r)
}

func fieldNameToArgName(fieldName string) string {
	if fieldName == "ID" {
		return fieldName
	}

	return lowercaseFirstRune(fieldName)
}

func newFieldOperationOneArgMethod(name, fieldName, argTypeName string) fieldOperationOneArgMethod {
	return fieldOperationOneArgMethod{
		onFieldMethod: newOnFieldMethod(name, fieldName),
		oneArgMethod:  newOneArgMethod(fieldNameToArgName(fieldName), argTypeName),
	}
}

// structOperationOneArgMethod

type structOperationOneArgMethod struct {
	baseMethod
	oneArgMethod
}

// GetBody returns method body
func (m structOperationOneArgMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s(%s)`, m.name, m.getArgName()))
}

func newStructOperationOneArgMethod(name, argTypeName string) structOperationOneArgMethod {
	return structOperationOneArgMethod{
		baseMethod:   newBaseMethod(name),
		oneArgMethod: newOneArgMethod(strings.ToLower(name), argTypeName),
	}
}

// binaryFilterMethod

type binaryFilterMethod struct {
	fieldOperationOneArgMethod
}

func newBinaryFilterMethod(name, fieldName, argTypeName string) binaryFilterMethod {
	return binaryFilterMethod{
		fieldOperationOneArgMethod: newFieldOperationOneArgMethod(name, fieldName, argTypeName),
	}
}

// GetBody returns method's code
func (m binaryFilterMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.Where("%s %s", %s)`,
		gorm.ToDBName(m.fieldName), m.getWhereCondition(), m.getArgName()))
}

func (m binaryFilterMethod) getWhereCondition() string {
	nameToOp := map[string]string{
		"eq":  "=",
		"ne":  "!=",
		"lt":  "<",
		"lte": "<=",
		"gt":  ">",
		"gte": ">=",
	}
	op := nameToOp[m.name]
	if op == "" {
		log.Fatalf("no operation for filter %q", m.name)
	}

	return fmt.Sprintf("%s ?", op)
}

// Concrete methods

func newPreloadMethod(fieldName string) fieldOperationNoArgsMethod {
	return newFieldOperationNoArgsMethod("Preload", fieldName)
}

func newOrderByMethod(fieldName string) fieldOperationNoArgsMethod {
	r := newFieldOperationNoArgsMethod("OrderBy", fieldName)
	r.setGormMethodName("Order")
	return r
}

func newLimitMethod() structOperationOneArgMethod {
	return newStructOperationOneArgMethod("Limit", "int")
}
<commit_msg>fix fieldname translation<commit_after>package queryset

import (
	"fmt"
	"log"
	"strings"
	"unicode"

	"github.com/jinzhu/gorm"
)

type method interface {
	GetMethodName() string
	GetArgsDeclaration() string
	GetBody() string
}

// baseMethod

type baseMethod struct {
	name string
}

func newBaseMethod(name string) baseMethod {
	return baseMethod{
		name: name,
	}
}

// GetMethodName returns name of method
func (m baseMethod) GetMethodName() string {
	return m.name
}

func (m baseMethod) wrapMethod(code string) string {
	const tmpl = `qs.db = qs.db.Scopes(func(d *gorm.DB) *gorm.DB {
      %s})
    return qs`
	return fmt.Sprintf(tmpl, code)
}

// onFieldMethod

type onFieldMethod struct {
	baseMethod
	fieldName        string
	isFieldNameFirst bool
}

func (m *onFieldMethod) setFieldNameFirst(isFieldNameFirst bool) {
	m.isFieldNameFirst = isFieldNameFirst
}

// GetMethodName returns name of method
func (m onFieldMethod) GetMethodName() string {
	args := []string{m.fieldName, strings.Title(m.name)}
	if !m.isFieldNameFirst {
		args[0], args[1] = args[1], args[0]
	}
	return args[0] + args[1]
}

func newOnFieldMethod(name, fieldName string) onFieldMethod {
	return onFieldMethod{
		baseMethod:       newBaseMethod(name),
		fieldName:        fieldName,
		isFieldNameFirst: true,
	}
}

// oneArgMethod

type oneArgMethod struct {
	argName     string
	argTypeName string
}

func (m oneArgMethod) getArgName() string {
	return m.argName
}

// GetArgsDeclaration returns declaration of arguments list for func decl
func (m oneArgMethod) GetArgsDeclaration() string {
	return fmt.Sprintf("%s %s", m.getArgName(), m.argTypeName)
}

func newOneArgMethod(argName, argTypeName string) oneArgMethod {
	return oneArgMethod{
		argName:     argName,
		argTypeName: argTypeName,
	}
}

// noArgsMethod

type noArgsMethod struct{}

// GetArgsDeclaration returns declaration of arguments list for func decl
func (m noArgsMethod) GetArgsDeclaration() string {
	return ""
}

// fieldOperationNoArgsMethod

// fieldOperationNoArgsMethod is for unary operations: preload, orderby, etc
type fieldOperationNoArgsMethod struct {
	onFieldMethod
	noArgsMethod
	gormMethodName string
}

func (m *fieldOperationNoArgsMethod) setGormMethodName(name string) {
	m.gormMethodName = name
}

// GetBody returns method body
func (m fieldOperationNoArgsMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s("%s")`, m.gormMethodName, gorm.ToDBName(m.fieldName)))
}

func newFieldOperationNoArgsMethod(name, fieldName string) fieldOperationNoArgsMethod {
	r := fieldOperationNoArgsMethod{
		onFieldMethod:  newOnFieldMethod(name, fieldName),
		gormMethodName: name,
	}
	r.setFieldNameFirst(false) // UserPreload -> PreloadUser
	return r
}

// fieldOperationOneArgMethod

type fieldOperationOneArgMethod struct {
	onFieldMethod
	oneArgMethod
}

// GetBody returns method body
func (m fieldOperationOneArgMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s(%s)`, m.name, m.getArgName()))
}

func lowercaseFirstRune(s string) string {
	r := []rune(s)
	r[0] = unicode.ToLower(r[0])
	return string(r)
}

func fieldNameToArgName(fieldName string) string {
	if fieldName == "ID" {
		return fieldName
	}

	return lowercaseFirstRune(fieldName)
}

func newFieldOperationOneArgMethod(name, fieldName, argTypeName string) fieldOperationOneArgMethod {
	return fieldOperationOneArgMethod{
		onFieldMethod: newOnFieldMethod(name, fieldName),
		oneArgMethod:  newOneArgMethod(fieldNameToArgName(fieldName), argTypeName),
	}
}

// structOperationOneArgMethod

type structOperationOneArgMethod struct {
	baseMethod
	oneArgMethod
}

// GetBody returns method body
func (m structOperationOneArgMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.%s(%s)`, m.name, m.getArgName()))
}

func newStructOperationOneArgMethod(name, argTypeName string) structOperationOneArgMethod {
	return structOperationOneArgMethod{
		baseMethod:   newBaseMethod(name),
		oneArgMethod: newOneArgMethod(strings.ToLower(name), argTypeName),
	}
}

// binaryFilterMethod

type binaryFilterMethod struct {
	fieldOperationOneArgMethod
}

func newBinaryFilterMethod(name, fieldName, argTypeName string) binaryFilterMethod {
	return binaryFilterMethod{
		fieldOperationOneArgMethod: newFieldOperationOneArgMethod(name, fieldName, argTypeName),
	}
}

// GetBody returns method's code
func (m binaryFilterMethod) GetBody() string {
	return m.wrapMethod(fmt.Sprintf(`return d.Where("%s %s", %s)`,
		gorm.ToDBName(m.fieldName), m.getWhereCondition(), m.getArgName()))
}

func (m binaryFilterMethod) getWhereCondition() string {
	nameToOp := map[string]string{
		"eq":  "=",
		"ne":  "!=",
		"lt":  "<",
		"lte": "<=",
		"gt":  ">",
		"gte": ">=",
	}
	op := nameToOp[m.name]
	if op == "" {
		log.Fatalf("no operation for filter %q", m.name)
	}

	return fmt.Sprintf("%s ?", op)
}

// Concrete methods

func newPreloadMethod(fieldName string) fieldOperationNoArgsMethod {
	return newFieldOperationNoArgsMethod("Preload", fieldName)
}

func newOrderByMethod(fieldName string) fieldOperationNoArgsMethod {
	r := newFieldOperationNoArgsMethod("OrderBy", fieldName)
	r.setGormMethodName("Order")
	return r
}

func newLimitMethod() structOperationOneArgMethod {
	return newStructOperationOneArgMethod("Limit", "int")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/prometheus/client_golang/prometheus"

	"github.com/infinityworks/prometheus-rancher-exporter/measure"
)

const (
	namespace           = "rancher" // Used to prepand Prometheus metrics created by this exporter.
	defaultLabelsFilter = "^io.prometheus"
)

// Runtime variables, user controllable for targeting, authentication and filtering.
var (
	log = logrus.New()

	metricsPath   = getEnv("METRICS_PATH", "/metrics")            // Path under which to expose metrics
	listenAddress = getEnv("LISTEN_ADDRESS", ":9173")             // Address on which to expose metrics
	rancherURL    = os.Getenv("CATTLE_URL")                       // URL of Rancher Server API e.g. http://192.168.0.1:8080/v2-beta
	accessKey     = os.Getenv("CATTLE_ACCESS_KEY")                // Optional - Access Key for Rancher API
	secretKey     = os.Getenv("CATTLE_SECRET_KEY")                // Optional - Secret Key for Rancher API
	labelsFilter  = os.Getenv("LABELS_FILTER")                    // Optional - Filter for Rancher label names
	logLevel      = getEnv("LOG_LEVEL", "info")                   // Optional - Set the logging level
	resourceLimit = getEnv("API_LIMIT", "100")                    // Optional - Rancher API resource limit (default: 100)
	hideSys, _    = strconv.ParseBool(getEnv("HIDE_SYS", "true")) // hideSys - Optional - Flag that indicates if the environment variable `HIDE_SYS` is set to a boolean true value
)

// Predefined variables that are used throughout the exporter
var (
	agentStates     = []string{"activating", "active", "reconnecting", "disconnected", "disconnecting", "finishing-reconnect", "reconnected"}
	clusterStates   = []string{"active", "cordoned", "degraded", "disconnected", "drained", "draining", "healthy", "initializing", "locked", "purged", "purging", "reconnecting", "reinitializing", "removed", "running", "unavailable", "unhealthy", "upgraded", "upgrading"}
	hostStates      = []string{"activating", "active", "deactivating", "disconnected", "error", "erroring", "inactive", "provisioned", "purged", "purging", "reconnecting", "registering", "removed", "removing", "requested", "restoring", "updating_active", "updating_inactive"}
	stackStates     = []string{"activating", "active", "canceled_upgrade", "canceling_upgrade", "error", "erroring", "finishing_upgrade", "removed", "removing", "requested", "restarting", "rolling_back", "updating_active", "upgraded", "upgrading"}
	serviceStates   = []string{"activating", "active", "canceled_upgrade", "canceling_upgrade", "deactivating", "finishing_upgrade", "inactive", "registering", "removed", "removing", "requested", "restarting", "rolling_back", "updating_active", "updating_inactive", "upgraded", "upgrading"}
	healthStates    = []string{"healthy", "unhealthy", "initializing", "degraded", "started-once"}
	componentStatus = []string{"True", "False", "Unknown"}
	nodeStates      = []string{"active", "cordoned", "degraded", "disconnected", "drained", "draining", "healthy", "initializing", "locked", "purged", "purging", "reconnecting", "reinitializing", "removed", "running", "unavailable", "unhealthy", "upgraded", "upgrading"}
	endpoints       = []string{"stacks", "services", "hosts"} // EndPoints the exporter will trawl
	endpointsV3     = []string{"clusters", "nodes"} // EndPoints the exporter will trawl]
	stackRef        = make(map[string]string)                 // Stores the StackID and StackName as a map, used to provide label dimensions to service metrics
	clusterRef      = make(map[string]string)	                // Stores the ClusterID and ClusterName as a map, used to provide label dimensions to node metrics
)

// getEnv - Allows us to supply a fallback option if nothing specified
func getEnv(key, fallback string) string {
	value := os.Getenv(key)
	if len(value) == 0 {
		return fallback
	}
	return value
}

func main() {
	flag.Parse()

	// Sets the logging value for the exporter, defaults to info
	setLogLevel(logLevel)

	// check the rancherURL ($CATTLE_URL) has been provided correctly
	if rancherURL == "" {
		log.Fatal("CATTLE_URL must be set and non-empty")
	}
	if strings.HasSuffix(rancherURL, "v3") || strings.HasSuffix(rancherURL, "v3/") {
		apiV3Flag = true
	}
	if labelsFilter == "" {
		labelsFilter = defaultLabelsFilter
	}

	labelsFilterRegexp, err := regexp.Compile(labelsFilter)
	if err != nil {
		log.Fatal("LABELS_FILTER must be valid regular expression")
	}

	log.Info("Starting Prometheus Exporter for Rancher")
	log.Info(
		"Runtime Configuration in-use: URL of Rancher Server: ",
		rancherURL,
		" Access key: ",
		accessKey,
		" System services hidden: ",
		hideSys,
		" Labels filter: ",
		labelsFilter,
	)

	// Register internal metrics used for tracking the exporter performance
	measure.Init()

	// Register a new Exporter
	exporter := newExporter(rancherURL, accessKey, secretKey, labelsFilterRegexp, hideSys, resourceLimit)

	// Register Metrics from each of the endpoints
	// This invokes the Collect method through the prometheus client libraries.
	prometheus.MustRegister(exporter)

	// Setup HTTP handler
	http.Handle(metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
		                <title>Rancher exporter</title>

rancher exporter

<a href='` + metricsPath + `'>Metrics

		              `))
	})
	log.Printf("Starting Server on port %s and path %s", listenAddress, metricsPath)
	log.Fatal(http.ListenAndServe(listenAddress, nil))
}
<commit_msg>delelte unused code<commit_after>package main

import (
	"flag"
	"net/http"
	"os"
	"regexp"
	"strconv"

	"github.com/Sirupsen/logrus"
	"github.com/infinityworks/prometheus-rancher-exporter/measure"
	"github.com/prometheus/client_golang/prometheus"
)

const (
	namespace           = "rancher" // Used to prepand Prometheus metrics created by this exporter.
	defaultLabelsFilter = "^io.prometheus"
)

// Runtime variables, user controllable for targeting, authentication and filtering.
var (
	log = logrus.New()

	metricsPath   = getEnv("METRICS_PATH", "/metrics")            // Path under which to expose metrics
	listenAddress = getEnv("LISTEN_ADDRESS", ":9173")             // Address on which to expose metrics
	rancherURL    = os.Getenv("CATTLE_URL")                       // URL of Rancher Server API e.g. http://192.168.0.1:8080/v2-beta
	accessKey     = os.Getenv("CATTLE_ACCESS_KEY")                // Optional - Access Key for Rancher API
	secretKey     = os.Getenv("CATTLE_SECRET_KEY")                // Optional - Secret Key for Rancher API
	labelsFilter  = os.Getenv("LABELS_FILTER")                    // Optional - Filter for Rancher label names
	logLevel      = getEnv("LOG_LEVEL", "info")                   // Optional - Set the logging level
	resourceLimit = getEnv("API_LIMIT", "100")                    // Optional - Rancher API resource limit (default: 100)
	hideSys, _    = strconv.ParseBool(getEnv("HIDE_SYS", "true")) // hideSys - Optional - Flag that indicates if the environment variable `HIDE_SYS` is set to a boolean true value
)

// Predefined variables that are used throughout the exporter
var (
	agentStates     = []string{"activating", "active", "reconnecting", "disconnected", "disconnecting", "finishing-reconnect", "reconnected"}
	clusterStates   = []string{"active", "cordoned", "degraded", "disconnected", "drained", "draining", "healthy", "initializing", "locked", "purged", "purging", "reconnecting", "reinitializing", "removed", "running", "unavailable", "unhealthy", "upgraded", "upgrading"}
	hostStates      = []string{"activating", "active", "deactivating", "disconnected", "error", "erroring", "inactive", "provisioned", "purged", "purging", "reconnecting", "registering", "removed", "removing", "requested", "restoring", "updating_active", "updating_inactive"}
	stackStates     = []string{"activating", "active", "canceled_upgrade", "canceling_upgrade", "error", "erroring", "finishing_upgrade", "removed", "removing", "requested", "restarting", "rolling_back", "updating_active", "upgraded", "upgrading"}
	serviceStates   = []string{"activating", "active", "canceled_upgrade", "canceling_upgrade", "deactivating", "finishing_upgrade", "inactive", "registering", "removed", "removing", "requested", "restarting", "rolling_back", "updating_active", "updating_inactive", "upgraded", "upgrading"}
	healthStates    = []string{"healthy", "unhealthy", "initializing", "degraded", "started-once"}
	componentStatus = []string{"True", "False", "Unknown"}
	nodeStates      = []string{"active", "cordoned", "degraded", "disconnected", "drained", "draining", "healthy", "initializing", "locked", "purged", "purging", "reconnecting", "reinitializing", "removed", "running", "unavailable", "unhealthy", "upgraded", "upgrading"}
	endpoints       = []string{"stacks", "services", "hosts"} // EndPoints the exporter will trawl
	endpointsV3     = []string{"clusters", "nodes"} // EndPoints the exporter will trawl]
	stackRef        = make(map[string]string)                 // Stores the StackID and StackName as a map, used to provide label dimensions to service metrics
	clusterRef      = make(map[string]string)	                // Stores the ClusterID and ClusterName as a map, used to provide label dimensions to node metrics
)

// getEnv - Allows us to supply a fallback option if nothing specified
func getEnv(key, fallback string) string {
	value := os.Getenv(key)
	if len(value) == 0 {
		return fallback
	}
	return value
}

func main() {
	flag.Parse()

	// Sets the logging value for the exporter, defaults to info
	setLogLevel(logLevel)

	// check the rancherURL ($CATTLE_URL) has been provided correctly
	if rancherURL == "" {
		log.Fatal("CATTLE_URL must be set and non-empty")
	}

	if labelsFilter == "" {
		labelsFilter = defaultLabelsFilter
	}

	labelsFilterRegexp, err := regexp.Compile(labelsFilter)
	if err != nil {
		log.Fatal("LABELS_FILTER must be valid regular expression")
	}

	log.Info("Starting Prometheus Exporter for Rancher")
	log.Info(
		"Runtime Configuration in-use: URL of Rancher Server: ",
		rancherURL,
		" Access key: ",
		accessKey,
		" System services hidden: ",
		hideSys,
		" Labels filter: ",
		labelsFilter,
	)

	// Register internal metrics used for tracking the exporter performance
	measure.Init()

	// Register a new Exporter
	exporter := newExporter(rancherURL, accessKey, secretKey, labelsFilterRegexp, hideSys, resourceLimit)

	// Register Metrics from each of the endpoints
	// This invokes the Collect method through the prometheus client libraries.
	prometheus.MustRegister(exporter)

	// Setup HTTP handler
	http.Handle(metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
		                <title>Rancher exporter</title>

rancher exporter

<a href='` + metricsPath + `'>Metrics

		              `))
	})
	log.Printf("Starting Server on port %s and path %s", listenAddress, metricsPath)
	log.Fatal(http.ListenAndServe(listenAddress, nil))
}
<|endoftext|>


<commit_before>package decoder

import (
	"fmt"

	"github.com/phpor/go/rdb"
)

type diff struct {
	db int
	i  int
	rdb.Nopdiff
}

func (p *diff) StartDatabase(n int) {
	p.db = n
}

func (p *diff) Set(key, value []byte, expiry int64) {
	fmt.Printf("db=%d %q -> %q\n", p.db, key, value)
}

func (p *diff) Hset(key, field, value []byte) {
	fmt.Printf("db=%d %q . %q -> %q\n", p.db, key, field, value)
}

func (p *diff) Sadd(key, member []byte) {
	fmt.Printf("db=%d %q { %q }\n", p.db, key, member)
}

func (p *diff) StartList(key []byte, length, expiry int64) {
	p.i = 0
}

func (p *diff) Rpush(key, value []byte) {
	fmt.Printf("db=%d %q[%d] -> %q\n", p.db, key, p.i, value)
	p.i++
}

func (p *diff) Zadd(key []byte, score float64, member []byte) {
	fmt.Printf("db=%d %q[%d] -> {%q, score=%g}\n", p.db, key, p.i, member, score)
	p.i++
}

func (p *diff) StartZSet(key []byte, cardinality, expiry int64) {
	p.i = 0
}
<commit_msg>Update diff.go<commit_after>package decoder

import (
	"fmt"

	"github.com/phpor/go/rdb"
)

type Diff struct {
	db int
	i  int
	rdb.NopDecoder
}

func (p *Diff) StartDatabase(n int) {
	p.db = n
}

func (p *Diff) Set(key, value []byte, expiry int64) {
	fmt.Printf("db=%d %q -> %q\n", p.db, key, value)
}

func (p *Diff) Hset(key, field, value []byte) {
	fmt.Printf("db=%d %q . %q -> %q\n", p.db, key, field, value)
}

func (p *Diff) Sadd(key, member []byte) {
	fmt.Printf("db=%d %q { %q }\n", p.db, key, member)
}

func (p *Diff) StartList(key []byte, length, expiry int64) {
	p.i = 0
}

func (p *Diff) Rpush(key, value []byte) {
	fmt.Printf("db=%d %q[%d] -> %q\n", p.db, key, p.i, value)
	p.i++
}

func (p *Diff) Zadd(key []byte, score float64, member []byte) {
	fmt.Printf("db=%d %q[%d] -> {%q, score=%g}\n", p.db, key, p.i, member, score)
	p.i++
}

func (p *Diff) StartZSet(key []byte, cardinality, expiry int64) {
	p.i = 0
}
<|endoftext|>