<commit_before>package redis

import (
	"errors"
	"log"
	"strings"
	"time"

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

const (
	REDIS_KEYWORD_HSET            = "HSET"
	REDIS_KEYWORD_HGET            = "HGET"
	REDIS_KEYWORD_HDEL            = "HDEL"
	REDIS_KEYWORD_HGETALL         = "HGETALL"
	REDIS_KEYWORD_SET             = "SET"
	REDIS_KEYWORD_SETNX           = "SETNX"
	REDIS_KEYWORD_SETEX           = "SETEX"
	REDIS_KEYWORD_GET             = "GET"
	REDIS_KEYWORD_STRLEN          = "STRLEN"
	REDIS_KEYWORD_EXPIRE          = "EXPIRE"
	REDIS_KEYWORD_DELETE          = "DEL"
	REDIS_KEYWORD_KEYS            = "KEYS"
	REDIS_KEYWORD_HKEYS           = "HKEYS"
	REDIS_KEYWORD_EXISTS          = "EXISTS"
	REDIS_KEYWORD_PERSIST         = "PERSIST"
	REDIS_KEYWORD_ZADD            = "ZADD"
	REDIS_KEYWORD_ZREM            = "ZREM"
	REDIS_KEYWORD_ZRANGE          = "ZRANGE"
	REDIS_KEYWORD_ZRANGE_BY_SCORE = "ZRANGEBYSCORE"
	REDIS_KEYWORD_WITHSCORES      = "WITHSCORES"
	REDIS_KEYWORD_INCR            = "INCR"
	REDIS_KEYWORD_DECR            = "DECR"
	REDIS_KEYWORD_INCRBY          = "INCRBY"
	REDIS_KEYWORD_DECRBY          = "DECRBY"
	REDIS_KEYWORD_INCRBYFLOAT     = "INCRBYFLOAT"
	REDIS_KEYWORD_DECRBYFLOAT     = "DECRBYFLOAT"
)

type Config struct {
	Server              string
	Password            string
	KEY_PREFIX          string // prefix to all keys; example is "dev environment name"
	KEY_DELIMITER       string // delimiter to be used while appending keys; example is ":"
	KEY_VAR_PLACEHOLDER string // placeholder to be parsed using given arguments to obtain a final key; example is "?"
}

var conf Config

func NewRConnectionPool(c Config) *redigo.Pool {
	conf = c
	return &redigo.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redigo.Conn, error) {
			c, err := redigo.Dial("tcp", conf.Server)
			if err != nil {
				log.Println("redigo-wrapper: Redis: Dial failed", err)
				return nil, err
			}
			if _, err := c.Do("AUTH", conf.Password); err != nil && conf.Password != "" {
				log.Println("redigo-wrapper: Redis: AUTH failed", err)
				c.Close()
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redigo.Conn, t time.Time) error {
			_, err := c.Do("PING")
			if err != nil {
				log.Println("redigo-wrapper: Unable to ping to redis server:", err)
			}
			return err
		},
	}
}

func ParseKey(key string, vars []string) (string, error) {
	arr := strings.Split(key, conf.KEY_VAR_PLACEHOLDER)
	actualKey := ""
	if len(arr) != len(vars)+1 {
		return "", errors.New("redis/connection.go: Insufficient arguments to parse key")
	} else {
		for index, val := range arr {
			if index == 0 {
				actualKey = arr[index]
			} else {
				actualKey += vars[index-1] + val
			}
		}
	}
	return getPrefixedKey(actualKey), nil
}

func getPrefixedKey(key string) string {
	return conf.KEY_PREFIX + conf.KEY_DELIMITER + key
}
func StripEnvKey(key string) string {
	return strings.TrimLeft(key, conf.KEY_PREFIX+conf.KEY_DELIMITER)
}
func SplitKey(key string) []string {
	return strings.Split(key, conf.KEY_DELIMITER)
}
func Expire(RConn *redigo.Conn, key string, ttl int) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_EXPIRE, key, ttl)
}
func Persist(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_PERSIST, key)
}

func Delete(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_DELETE, key)
}
func Set(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	//set
	return (*RConn).Do(REDIS_KEYWORD_SET, key, data)
}
func SetNX(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_SETNX, key, data)
}
func SetEx(RConn *redigo.Conn, key string, ttl int, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_SETEX, key, ttl, data)
}
func Get(RConn *redigo.Conn, key string) (interface{}, error) {
	//get
	return (*RConn).Do(REDIS_KEYWORD_GET, key)
}
func GetString(RConn *redigo.Conn, key string) (string, error) {
	return redigo.String((*RConn).Do(REDIS_KEYWORD_GET, key))
}
func GetInt(RConn *redigo.Conn, key string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_GET, key))
}
func GetStringLength(RConn *redigo.Conn, key string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_STRLEN, key))
}
func ZAdd(RConn *redigo.Conn, key string, score float64, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_ZADD, key, score, data)
}
func ZRem(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_ZREM, key, data)
}
func ZRange(RConn *redigo.Conn, key string, start int, end int, withScores bool) ([]interface{}, error) {
	if withScores {
		return redigo.Values((*RConn).Do(REDIS_KEYWORD_ZRANGE, key, start, end, REDIS_KEYWORD_WITHSCORES))
	}
	return redigo.Values((*RConn).Do(REDIS_KEYWORD_ZRANGE, key, start, end))
}
func HSet(RConn *redigo.Conn, key string, HKey string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HSET, key, HKey, data)
}

func HGet(RConn *redigo.Conn, key string, HKey string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HGET, key, HKey)
}
func HGetString(RConn *redigo.Conn, key string, HKey string) (string, error) {
	return redigo.String((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetFloat(RConn *redigo.Conn, key string, HKey string) (float64, error) {
	f, err := redigo.Float64((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
	return float64(f), err
}
func HGetInt(RConn *redigo.Conn, key string, HKey string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetInt64(RConn *redigo.Conn, key string, HKey string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetBool(RConn *redigo.Conn, key string, HKey string) (bool, error) {
	return redigo.Bool((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HDel(RConn *redigo.Conn, key string, HKey string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HDEL, key, HKey)
}
func HGetAll(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HGETALL, key)
}

func HGetAllValues(RConn *redigo.Conn, key string) ([]interface{}, error) {
	return redigo.Values((*RConn).Do(REDIS_KEYWORD_HGETALL, key))
}
func HGetAllString(RConn *redigo.Conn, key string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_HGETALL, key))
}

func Keys(RConn *redigo.Conn, pattern string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_KEYS, pattern))
}

func HKeys(RConn *redigo.Conn, key string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_HKEYS, key))
}

func Exists(RConn *redigo.Conn, key string) (bool, error) {
	count, err := redigo.Int((*RConn).Do(REDIS_KEYWORD_EXISTS, key))
	if count == 0 {
		return false, err
	} else {
		return true, err
	}
}

func Incr(RConn *redigo.Conn, key string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_INCR, key))
}

func Decr(RConn *redigo.Conn, key string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_DECR, key))
}

func IncrBy(RConn *redigo.Conn, key string, incBy int64) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_INCRBY, key, incBy))
}

func DecrBy(RConn *redigo.Conn, key string, decrBy int64) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_DECRBY, key))
}

func IncrByFloat(RConn *redigo.Conn, key string, incBy float64) (float64, error) {
	return redigo.Float64((*RConn).Do(REDIS_KEYWORD_INCRBYFLOAT, key, incBy))
}

func DecrByFloat(RConn *redigo.Conn, key string, decrBy float64) (float64, error) {
	return redigo.Float64((*RConn).Do(REDIS_KEYWORD_DECRBYFLOAT, key, decrBy))
}
<commit_msg>take additional params to configure RPool<commit_after>package redis

import (
	"errors"
	"log"
	"strings"
	"time"

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

const (
	REDIS_KEYWORD_HSET            = "HSET"
	REDIS_KEYWORD_HGET            = "HGET"
	REDIS_KEYWORD_HDEL            = "HDEL"
	REDIS_KEYWORD_HGETALL         = "HGETALL"
	REDIS_KEYWORD_SET             = "SET"
	REDIS_KEYWORD_SETNX           = "SETNX"
	REDIS_KEYWORD_SETEX           = "SETEX"
	REDIS_KEYWORD_GET             = "GET"
	REDIS_KEYWORD_STRLEN          = "STRLEN"
	REDIS_KEYWORD_EXPIRE          = "EXPIRE"
	REDIS_KEYWORD_DELETE          = "DEL"
	REDIS_KEYWORD_KEYS            = "KEYS"
	REDIS_KEYWORD_HKEYS           = "HKEYS"
	REDIS_KEYWORD_EXISTS          = "EXISTS"
	REDIS_KEYWORD_PERSIST         = "PERSIST"
	REDIS_KEYWORD_ZADD            = "ZADD"
	REDIS_KEYWORD_ZREM            = "ZREM"
	REDIS_KEYWORD_ZRANGE          = "ZRANGE"
	REDIS_KEYWORD_ZRANGE_BY_SCORE = "ZRANGEBYSCORE"
	REDIS_KEYWORD_WITHSCORES      = "WITHSCORES"
	REDIS_KEYWORD_INCR            = "INCR"
	REDIS_KEYWORD_DECR            = "DECR"
	REDIS_KEYWORD_INCRBY          = "INCRBY"
	REDIS_KEYWORD_DECRBY          = "DECRBY"
	REDIS_KEYWORD_INCRBYFLOAT     = "INCRBYFLOAT"
	REDIS_KEYWORD_DECRBYFLOAT     = "DECRBYFLOAT"
)

type Config struct {
	Server   string
	Password string
	MaxIdle  int // Maximum number of idle connections in the pool.

	// Maximum number of connections allocated by the pool at a given time.
	// When zero, there is no limit on the number of connections in the pool.
	MaxActive int

	// Close connections after remaining idle for this duration. If the value
	// is zero, then idle connections are not closed. Applications should set
	// the timeout to a value less than the server's timeout.
	IdleTimeout time.Duration

	// If Wait is true and the pool is at the MaxActive limit, then Get() waits
	// for a connection to be returned to the pool before returning.
	Wait                bool
	KEY_PREFIX          string // prefix to all keys; example is "dev environment name"
	KEY_DELIMITER       string // delimiter to be used while appending keys; example is ":"
	KEY_VAR_PLACEHOLDER string // placeholder to be parsed using given arguments to obtain a final key; example is "?"
}

var conf Config

func NewRConnectionPool(c Config) *redigo.Pool {
	conf = c
	return &redigo.Pool{
		MaxIdle:     conf.MaxIdle,
		IdleTimeout: conf.IdleTimeout,
		MaxActive:   conf.MaxActive,
		Wait:        conf.Wait,
		Dial: func() (redigo.Conn, error) {
			c, err := redigo.Dial("tcp", conf.Server)
			if err != nil {
				log.Println("redigo-wrapper: Redis: Dial failed", err)
				return nil, err
			}
			if _, err := c.Do("AUTH", conf.Password); err != nil && conf.Password != "" {
				log.Println("redigo-wrapper: Redis: AUTH failed", err)
				c.Close()
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redigo.Conn, t time.Time) error {
			_, err := c.Do("PING")
			if err != nil {
				log.Println("redigo-wrapper: Unable to ping to redis server:", err)
			}
			return err
		},
	}
}

func ParseKey(key string, vars []string) (string, error) {
	arr := strings.Split(key, conf.KEY_VAR_PLACEHOLDER)
	actualKey := ""
	if len(arr) != len(vars)+1 {
		return "", errors.New("redis/connection.go: Insufficient arguments to parse key")
	} else {
		for index, val := range arr {
			if index == 0 {
				actualKey = arr[index]
			} else {
				actualKey += vars[index-1] + val
			}
		}
	}
	return getPrefixedKey(actualKey), nil
}

func getPrefixedKey(key string) string {
	return conf.KEY_PREFIX + conf.KEY_DELIMITER + key
}
func StripEnvKey(key string) string {
	return strings.TrimLeft(key, conf.KEY_PREFIX+conf.KEY_DELIMITER)
}
func SplitKey(key string) []string {
	return strings.Split(key, conf.KEY_DELIMITER)
}
func Expire(RConn *redigo.Conn, key string, ttl int) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_EXPIRE, key, ttl)
}
func Persist(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_PERSIST, key)
}

func Delete(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_DELETE, key)
}
func Set(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	//set
	return (*RConn).Do(REDIS_KEYWORD_SET, key, data)
}
func SetNX(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_SETNX, key, data)
}
func SetEx(RConn *redigo.Conn, key string, ttl int, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_SETEX, key, ttl, data)
}
func Get(RConn *redigo.Conn, key string) (interface{}, error) {
	//get
	return (*RConn).Do(REDIS_KEYWORD_GET, key)
}
func GetString(RConn *redigo.Conn, key string) (string, error) {
	return redigo.String((*RConn).Do(REDIS_KEYWORD_GET, key))
}
func GetInt(RConn *redigo.Conn, key string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_GET, key))
}
func GetStringLength(RConn *redigo.Conn, key string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_STRLEN, key))
}
func ZAdd(RConn *redigo.Conn, key string, score float64, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_ZADD, key, score, data)
}
func ZRem(RConn *redigo.Conn, key string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_ZREM, key, data)
}
func ZRange(RConn *redigo.Conn, key string, start int, end int, withScores bool) ([]interface{}, error) {
	if withScores {
		return redigo.Values((*RConn).Do(REDIS_KEYWORD_ZRANGE, key, start, end, REDIS_KEYWORD_WITHSCORES))
	}
	return redigo.Values((*RConn).Do(REDIS_KEYWORD_ZRANGE, key, start, end))
}
func HSet(RConn *redigo.Conn, key string, HKey string, data interface{}) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HSET, key, HKey, data)
}

func HGet(RConn *redigo.Conn, key string, HKey string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HGET, key, HKey)
}
func HGetString(RConn *redigo.Conn, key string, HKey string) (string, error) {
	return redigo.String((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetFloat(RConn *redigo.Conn, key string, HKey string) (float64, error) {
	f, err := redigo.Float64((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
	return float64(f), err
}
func HGetInt(RConn *redigo.Conn, key string, HKey string) (int, error) {
	return redigo.Int((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetInt64(RConn *redigo.Conn, key string, HKey string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HGetBool(RConn *redigo.Conn, key string, HKey string) (bool, error) {
	return redigo.Bool((*RConn).Do(REDIS_KEYWORD_HGET, key, HKey))
}
func HDel(RConn *redigo.Conn, key string, HKey string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HDEL, key, HKey)
}
func HGetAll(RConn *redigo.Conn, key string) (interface{}, error) {
	return (*RConn).Do(REDIS_KEYWORD_HGETALL, key)
}

func HGetAllValues(RConn *redigo.Conn, key string) ([]interface{}, error) {
	return redigo.Values((*RConn).Do(REDIS_KEYWORD_HGETALL, key))
}
func HGetAllString(RConn *redigo.Conn, key string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_HGETALL, key))
}

func Keys(RConn *redigo.Conn, pattern string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_KEYS, pattern))
}

func HKeys(RConn *redigo.Conn, key string) ([]string, error) {
	return redigo.Strings((*RConn).Do(REDIS_KEYWORD_HKEYS, key))
}

func Exists(RConn *redigo.Conn, key string) (bool, error) {
	count, err := redigo.Int((*RConn).Do(REDIS_KEYWORD_EXISTS, key))
	if count == 0 {
		return false, err
	} else {
		return true, err
	}
}

func Incr(RConn *redigo.Conn, key string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_INCR, key))
}

func Decr(RConn *redigo.Conn, key string) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_DECR, key))
}

func IncrBy(RConn *redigo.Conn, key string, incBy int64) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_INCRBY, key, incBy))
}

func DecrBy(RConn *redigo.Conn, key string, decrBy int64) (int64, error) {
	return redigo.Int64((*RConn).Do(REDIS_KEYWORD_DECRBY, key))
}

func IncrByFloat(RConn *redigo.Conn, key string, incBy float64) (float64, error) {
	return redigo.Float64((*RConn).Do(REDIS_KEYWORD_INCRBYFLOAT, key, incBy))
}

func DecrByFloat(RConn *redigo.Conn, key string, decrBy float64) (float64, error) {
	return redigo.Float64((*RConn).Do(REDIS_KEYWORD_DECRBYFLOAT, key, decrBy))
}
<|endoftext|>


<commit_before>package commands

import (
	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/spf13/cobra"
)

var (
	getCmd = &cobra.Command{
		Use:   "get",
		Short: "get",
		Run:   getCommand,
	}
)

func getCommand(cmd *cobra.Command, args []string) {
	var ref string
	var err error

	if len(args) == 1 {
		ref = args[0]
	} else {
		ref, err = git.CurrentRef()
		if err != nil {
			Panic(err, "Could not get")
		}
	}

	pointers, err := lfs.ScanRefs(ref, "")
	if err != nil {
		Panic(err, "Could not scan for Git LFS files")
	}

	q := lfs.NewDownloadQueue(lfs.Config.ConcurrentTransfers(), len(pointers))

	for _, p := range pointers {
		q.Add(p)
	}

	q.Process()
}

func init() {
	RootCmd.AddCommand(getCmd)
}
<commit_msg>ンンー ンンンン ンーンン<commit_after>package commands

import (
	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/spf13/cobra"
	"os"
)

var (
	getCmd = &cobra.Command{
		Use:   "get",
		Short: "get",
		Run:   getCommand,
	}
)

func getCommand(cmd *cobra.Command, args []string) {
	var ref string
	var err error

	if len(args) == 1 {
		ref = args[0]
	} else {
		ref, err = git.CurrentRef()
		if err != nil {
			Panic(err, "Could not get")
		}
	}

	pointers, err := lfs.ScanRefs(ref, "")
	if err != nil {
		Panic(err, "Could not scan for Git LFS files")
	}

	q := lfs.NewDownloadQueue(lfs.Config.ConcurrentTransfers(), len(pointers))

	for _, p := range pointers {
		q.Add(p)
	}

	q.Process()

	target, err := git.ResolveRef(ref)
	if err != nil {
	}

	current, err := git.CurrentRef()
	if err != nil {
	}

	if target == current {
		for _, pointer := range pointers {
			file, err := os.Create(pointer.Name)
			if err != nil {
				Panic(err, "Could not create working directory file")
			}

			err = lfs.PointerSmudge(file, pointer.Pointer, pointer.Name, nil)
			if err != nil {
				Panic(err, "Could not write working directory file")
			}
		}
	}
}

func init() {
	RootCmd.AddCommand(getCmd)
}
<|endoftext|>


<commit_before>/*
parser inspired by Rob Pikes lexer
*/

package parser

import (
	"errors"
	"fmt"
	"strings"
	"unicode/utf8"
)

// last State must return ErrEOF
type State func(p *Parser) (next State, err error)

var ErrEOF = errors.New("End of File")

var EOF = rune('∎')

type ASTNode interface {
	AddChild(ASTNode)
}

type Parser struct {
	astQueue    []ASTNode
	input       string // the string being scanned
	start       int    // start position of this item
	pos         int    // current position in the input
	width       int    // width of the last rune read
	line        int
	linepos     int
	linePrev    int
	lineposPrev int
}

func New(input string, root ASTNode) *Parser {
	return &Parser{
		astQueue: []ASTNode{root},
		input:    input,
	}
}

func (p *Parser) Root() ASTNode {
	return p.astQueue[0]
}

func (p *Parser) currentNode() ASTNode {
	return p.astQueue[len(p.astQueue)-1]
}

func (p *Parser) AddNode(n ASTNode) {
	p.currentNode().AddChild(n)
	p.astQueue = append(p.astQueue, n)
}

func (p *Parser) PopNode() {
	if len(p.astQueue) < 2 {
		return
	}
	p.astQueue = p.astQueue[:len(p.astQueue)-1]
}

func (p *Parser) Next() (rune_ rune) {
	if p.pos >= len(p.input) {
		p.width = 0
		return EOF
	}
	rune_, p.width = utf8.DecodeRuneInString(p.input[p.pos:])
	p.pos += p.width
	p.linePrev = p.line
	p.lineposPrev = p.linepos
	if rune_ == '\n' {
		p.line++
		p.linepos = 0
	} else {
		p.linepos++
	}

	return
}

// emit passes an item back to the client
func (p *Parser) Emit() string {
	s := p.input[p.start:p.pos]
	p.start = p.pos
	return s
}

func (p *Parser) Ignore() {
	p.start = p.pos
}

// backup steps back one rune
// can be called only once per call of next
func (p *Parser) Backup() {
	rune_, _ := utf8.DecodeRuneInString(p.input[p.pos:])
	if rune_ == '\n' {
		p.line--
	}
	p.linepos = p.lineposPrev
	p.pos -= p.width
}

func (p *Parser) Peek() rune {
	r := p.Next()
	p.Backup()
	return r
}

func (p *Parser) Accept(valid string) bool {
	if strings.IndexRune(valid, p.Next()) >= 0 {
		return true
	}
	p.Backup()
	return false
}

func (p *Parser) AcceptRun(valid string) {
	for strings.IndexRune(valid, p.Next()) >= 0 {
	}
	p.Backup()
}

// runs forward until one of the stopper
func (p *Parser) ForwardUntil(stopper string) {
	for strings.IndexRune(stopper, p.Next()) == -1 {
	}
	p.Backup()
}

func (p *Parser) Errorf(format string, args ...interface{}) error {
	start := p.pos - 5
	if start < 0 {
		start = 0
	}

	end := p.pos + 5

	if end > len(p.input) {
		end = len(p.input)
	}

	return errors.New(fmt.Sprintf(
		"Error in line %d at position %d: %s\ncontext:\n%s\n",
		p.line+1,
		p.linepos+1,
		fmt.Sprintf(format, args...),
		p.input[start:end],
	))
}

func (p *Parser) Run(fn State) (err error) {
	for err == nil {
		fn, err = fn(p)
	}
	if err == ErrEOF {
		return nil
	}

	return err
}
<commit_msg>track error in parser<commit_after>/*
parser inspired by Rob Pikes lexer
*/

package parser

import (
	"errors"
	"fmt"
	"strings"
	"unicode/utf8"
)

// last State must return ErrEOF
type State func(p *Parser) (next State)

var ErrEOF = errors.New("End of File")

var EOF = rune('∎')

type ASTNode interface {
	AddChild(ASTNode)
}

type Parser struct {
	astQueue    []ASTNode
	input       string // the string being scanned
	start       int    // start position of this item
	pos         int    // current position in the input
	width       int    // width of the last rune read
	line        int
	linepos     int
	linePrev    int
	lineposPrev int
	err         error
}

func New(input string, root ASTNode) *Parser {
	return &Parser{
		astQueue: []ASTNode{root},
		input:    input,
	}
}

func (p *Parser) Root() ASTNode {
	return p.astQueue[0]
}

func (p *Parser) currentNode() ASTNode {
	return p.astQueue[len(p.astQueue)-1]
}

func (p *Parser) AddNode(n ASTNode) {
	p.currentNode().AddChild(n)
	p.astQueue = append(p.astQueue, n)
}

func (p *Parser) PopNode() {
	if len(p.astQueue) < 2 {
		return
	}
	p.astQueue = p.astQueue[:len(p.astQueue)-1]
}

func (p *Parser) HasError() bool {
	return p.err == nil || p.err == ErrEOF
}

func (p *Parser) IsEOF() bool {
	return p.err == ErrEOF
}

func (p *Parser) Next() (rune_ rune) {
	if p.pos >= len(p.input) {
		p.width = 0
		p.err = ErrEOF
		return EOF
	}
	rune_, p.width = utf8.DecodeRuneInString(p.input[p.pos:])
	p.pos += p.width
	p.linePrev = p.line
	p.lineposPrev = p.linepos
	if rune_ == '\n' {
		p.line++
		p.linepos = 0
	} else {
		p.linepos++
	}

	return
}

// emit passes an item back to the client
func (p *Parser) Emit() string {
	s := p.input[p.start:p.pos]
	p.start = p.pos
	return s
}

func (p *Parser) Ignore() {
	p.start = p.pos
}

// backup steps back one rune
// can be called only once per call of next
func (p *Parser) Backup() {
	rune_, _ := utf8.DecodeRuneInString(p.input[p.pos:])
	if rune_ == '\n' {
		p.line--
	}
	p.linepos = p.lineposPrev
	p.pos -= p.width
}

func (p *Parser) Peek() rune {
	r := p.Next()
	p.Backup()
	return r
}

func (p *Parser) Accept(valid string) bool {
	if strings.IndexRune(valid, p.Next()) >= 0 {
		return true
	}
	p.Backup()
	return false
}

func (p *Parser) AcceptRun(valid string) {
	for strings.IndexRune(valid, p.Next()) >= 0 {
	}
	p.Backup()
}

// runs forward until one of the stopper
func (p *Parser) ForwardUntil(stopper string) {
	for strings.IndexRune(stopper, p.Next()) == -1 {
	}
	p.Backup()
}

func (p *Parser) Errorf(format string, args ...interface{}) {
	start := p.pos - 5
	if start < 0 {
		start = 0
	}

	end := p.pos + 5

	if end > len(p.input) {
		end = len(p.input)
	}

	p.err = errors.New(fmt.Sprintf(
		"Error in line %d at position %d: %s\ncontext:\n%s\n",
		p.line+1,
		p.linepos+1,
		fmt.Sprintf(format, args...),
		p.input[start:end],
	))
}

func (p *Parser) Run(fn State) (err error) {
	for p.err == nil {
		fn = fn(p)
	}
	if p.err == ErrEOF {
		return nil
	}

	return err
}
<|endoftext|>


<commit_before>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

type Parser struct {
	tokens    []*token
	pos       int
	Variables map[string]float64
	tok       *token
}

type association int

const (
	ASSOC_NONE association = iota
	ASSOC_LEFT
	ASSOC_RIGHT
)

type operator struct {
	prec  int
	assoc association
	unary bool
}

var allOperators = map[tokenType]operator{
	// Assignment operators
	EQ:     {0, ASSOC_RIGHT, false}, // =
	ADD_EQ: {0, ASSOC_RIGHT, false}, // +=
	SUB_EQ: {0, ASSOC_RIGHT, false}, // -=
	DIV_EQ: {0, ASSOC_RIGHT, false}, // /=
	MUL_EQ: {0, ASSOC_RIGHT, false}, // *=
	POW_EQ: {0, ASSOC_RIGHT, false}, // **=
	REM_EQ: {0, ASSOC_RIGHT, false}, // %=
	AND_EQ: {0, ASSOC_RIGHT, false}, // &=
	OR_EQ:  {0, ASSOC_RIGHT, false}, // |=
	XOR_EQ: {0, ASSOC_RIGHT, false}, // ^=
	LSH_EQ: {0, ASSOC_RIGHT, false}, // <<=
	RSH_EQ: {0, ASSOC_RIGHT, false}, // >>=

	// Relational operators
	EQ_EQ: {0, ASSOC_RIGHT, false}, // ==
	GT:    {0, ASSOC_RIGHT, false}, // >
	GT_EQ: {0, ASSOC_RIGHT, false}, // >=
	LT:    {0, ASSOC_RIGHT, false}, // <
	LT_EQ: {0, ASSOC_RIGHT, false}, // <=

	// Bitwise operators
	OR:  {1, ASSOC_RIGHT, false}, // |
	XOR: {2, ASSOC_RIGHT, false}, // ^
	AND: {3, ASSOC_RIGHT, false}, // &
	LSH: {4, ASSOC_RIGHT, false}, // <<
	RSH: {4, ASSOC_RIGHT, false}, // >>
	NOT: {8, ASSOC_LEFT, true},   // ~

	// Mathematical operators
	ADD:       {5, ASSOC_LEFT, false}, // +
	SUB:       {5, ASSOC_LEFT, false}, // -
	MUL:       {6, ASSOC_LEFT, false}, // *
	DIV:       {6, ASSOC_LEFT, false}, // /
	POW:       {7, ASSOC_LEFT, false}, // **
	REM:       {6, ASSOC_LEFT, false}, // %
	UNARY_MIN: {9, ASSOC_LEFT, true},  // -
}

var (
	divisionByZeroErr       = errors.New("Divison by zero")
	unmatchedParenthesesErr = errors.New("Unmatched parentheses")
	invalidSyntaxErr        = errors.New("Invalid syntax")
)

// Determine if operator 1 has higher precendence than operator 2
func (o1 operator) hasHigherPrecThan(o2 operator) bool {
	return (o2.assoc == ASSOC_LEFT && o2.prec <= o1.prec) ||
		(o2.assoc == ASSOC_RIGHT && o2.prec < o1.prec)
}

// Some useful predefined variables that can be used in expressions. These
// can be overwritten.
var constants = map[string]float64{
	"pi":  math.Pi,
	"tau": math.Pi / 2,
	"phi": math.Phi,
	"e":   math.E,
}

// New initializes a new Parser instance, useful when you want to run multiple
// expression and/or use variables.
func New() *Parser {
	return &Parser{
		pos:       0,
		Variables: constants,
	}
}

// Eval evaluates an expression and returns its result and any errors found.
//
// Example:
//     res, err := mathcat.Eval("2 * 2 * 2") // 8
func Eval(expr string) (float64, error) {
	tokens, err := Lex(expr)

	// If a lexer error occured don't parse
	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	return p.parse()
}

// Run executes an expression on an existing parser instance. Useful for
// variable assignment.
//
// Example:
//     p.Run("a = 555")
//     p.Run("a += 45")
//     res, err := p.Run("a + a") // 1200
func (p *Parser) Run(expr string) (float64, error) {
	tokens, err := Lex(expr)

	if err != nil {
		return -1, err
	}

	p.reset()
	p.tokens = tokens

	return p.parse()
}

// Exec executes an expression with a given map of variables.
//
// Example:
//     res, err := mathcat.Exec("a + b * b", map[string]float64{
//	       "a": 1,
//         "b": 3,
//     }) // 10
func Exec(expr string, vars map[string]float64) (float64, error) {
	tokens, err := Lex(expr)

	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	isValidIdent := func(c rune) bool { return isIdent(c) || isNumber(c) }

	for k, v := range vars {
		if !isIdent(rune(k[0])) || strings.IndexFunc(k, isValidIdent) == -1 {
			return -1, fmt.Errorf("Invalid variable name: '%s'")
		}
		p.Variables[k] = v
	}

	p.tokens = tokens

	return p.parse()
}

// GetVar gets an existing variable.
func (p *Parser) GetVar(index string) (float64, error) {
	if val, ok := p.Variables[index]; ok {
		return val, nil
	}

	return -1, fmt.Errorf("Undefined variable '%s'", index)
}

func (p *Parser) parse() (float64, error) {
	var (
		operands, operators stack
		o1, o2              operator
	)

	p.tok = p.tokens[0]

	for p.eat().Type != EOL {
		switch {
		case p.tok.IsLiteral():
			operands.Push(p.tok)
		case p.tok.Type == LPAREN:
			operators.Push(p.tok)
		case p.tok.IsOperator():
			o1 = allOperators[p.tok.Type]

			if !operators.Empty() {
				var ok bool
				if o2, ok = allOperators[operators.Top().(*token).Type]; !ok {
					operators.Push(p.tok)
					break
				}

				if o2.hasHigherPrecThan(o1) {
					operator := operators.Pop().(*token)
					val, err := p.evaluate(operator, &operands)
					if err != nil {
						return -1, err
					}
					operands.Push(val)
				}
			}
			operators.Push(p.tok)
		case p.tok.Type == RPAREN:
			for {
				if operators.Empty() {
					return -1, unmatchedParenthesesErr
				}

				operator := operators.Pop().(*token)
				if operator.Type == LPAREN {
					break
				}
				val, err := p.evaluate(operator, &operands)
				if err != nil {
					return -1, err
				}
				operands.Push(val)
			}
		}
	}

	// Evaluate remaing operators
	for !operators.Empty() {
		operator := operators.Pop().(*token)

		if operator.Type == LPAREN {
			return -1, unmatchedParenthesesErr
		}

		if operands.Empty() {
			return -1, invalidSyntaxErr
		}

		val, err := p.evaluate(operator, &operands)
		if err != nil {
			return -1, err
		}
		operands.Push(val)
	}

	// If there are no operands, the expression is useless and doesn't do
	// anything, for example `()` or an empty string
	if operands.Empty() {
		return 0, nil
	}

	// Single operand left means the expression was evaluated successful
	if len(operands) == 1 {
		return p.lookup(operands[0])
	}

	// Leftover token on operand stack indicates invalid syntax
	return -1, invalidSyntaxErr
}

func (p *Parser) evaluate(operator *token, operands *stack) (float64, error) {
	var (
		result      float64
		left, right float64
		err         error
		lhsToken    interface{}
	)

	if operands.Empty() {
		return -1, fmt.Errorf("Unexpected '%s'", operator.Type)
	}

	if right, err = p.lookup(operands.Pop()); err != nil {
		return -1, err
	}

	// Unary operators have no left hand side
	if op := allOperators[operator.Type]; !op.unary {
		if operands.Empty() {
			return -1, invalidSyntaxErr
		}
		// Save the token in case of a assignment variable is used and we need to
		// save the result in a variable
		lhsToken = operands.Pop()

		// Don't lookup the left hand side if = is used so we can do initial
		// assignment
		if operator.Type != EQ {
			left, err = p.lookup(lhsToken)
			if err != nil {
				return -1, err
			}
		}
	}

	result, err = execute(operator, left, right)
	if err != nil {
		return -1, err
	}

	switch operator.Type {
	case EQ, ADD_EQ, SUB_EQ, DIV_EQ, MUL_EQ, POW_EQ, REM_EQ, AND_EQ, OR_EQ, XOR_EQ, LSH_EQ, RSH_EQ:
		// Save result in variable
		if lhsToken.(*token).Type != IDENT {
			return -1, errors.New("Can't assign to literal")
		}
		p.Variables[lhsToken.(*token).Value] = result
	}

	return result, nil
}

func execute(operator *token, lhs, rhs float64) (float64, error) {
	var result float64

	// Both lhs and rhs have to be whole numbers for bitwise operations
	if operator.IsBitwise() && (!IsWholeNumber(lhs) || !IsWholeNumber(rhs)) {
		return -1, fmt.Errorf("Unsupported type (float) for '%s'", operator.Type)
	}

	switch operator.Type {
	case ADD, ADD_EQ:
		result = lhs + rhs
	case SUB, SUB_EQ:
		result = lhs - rhs
	case UNARY_MIN:
		result = -rhs
	case DIV, DIV_EQ:
		if rhs == 0 {
			return -1, divisionByZeroErr
		}
		result = lhs / rhs
	case MUL, MUL_EQ:
		result = lhs * rhs
	case POW, POW_EQ:
		result = math.Pow(lhs, rhs)
	case REM, REM_EQ:
		if rhs == 0 {
			return -1, divisionByZeroErr
		}
		result = math.Mod(lhs, rhs)
	case AND, AND_EQ:
		result = float64(int64(lhs) & int64(rhs))
	case OR, OR_EQ:
		result = float64(int64(lhs) | int64(rhs))
	case XOR, XOR_EQ:
		result = float64(int64(lhs) ^ int64(rhs))
	case LSH, LSH_EQ:
		result = float64(uint64(lhs) << uint64(rhs))
	case RSH, RSH_EQ:
		result = float64(uint64(lhs) >> uint64(rhs))
	case NOT:
		result = float64(^int64(rhs))
	case EQ:
		result = rhs
	case EQ_EQ:
		result = bool2float(lhs == rhs)
	case GT:
		result = bool2float(lhs > rhs)
	case GT_EQ:
		result = bool2float(lhs >= rhs)
	case LT:
		result = bool2float(lhs < rhs)
	case LT_EQ:
		result = bool2float(lhs <= rhs)
	default:
		return -1, fmt.Errorf("Invalid operator '%s'", operator.Type)
	}

	return result, nil
}

// Look up a literal. If it's an identifier, check the parser's variables map,
// otherwise convert the tokenized string to a float64.
func (p *Parser) lookup(val interface{}) (float64, error) {
	// val can be a token or a float64, if it's a float64 it has been already
	// evaluated and we don't need to do anything
	if v, ok := val.(float64); ok {
		return v, nil
	}

	tok := val.(*token)
	switch tok.Type {
	case NUMBER:
		return strconv.ParseFloat(tok.Value, 64)
	case IDENT:
		res, err := p.GetVar(tok.Value)
		if err != nil {
			return -1, err
		}

		return res, nil
	}

	return -1, fmt.Errorf("Invalid lookup type: %s", tok.Type)
}

func (p *Parser) reset() {
	p.tokens = nil
	p.pos = 0
}

func (p *Parser) peek() *token {
	return p.tokens[p.pos]
}

func (p *Parser) eat() *token {
	p.tok = p.peek()
	p.pos++
	return p.tok
}

// Check if a float is a whole number
func IsWholeNumber(n float64) bool {
	epsilon := 1e-9
	_, frac := math.Modf(math.Abs(n))

	return frac < epsilon || frac > 1.0-epsilon
}

func bool2float(b bool) float64 {
	if b {
		return 1
	}
	return 0
}
<commit_msg>Fix error variables name form<commit_after>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

type Parser struct {
	tokens    []*token
	pos       int
	Variables map[string]float64
	tok       *token
}

type association int

const (
	ASSOC_NONE association = iota
	ASSOC_LEFT
	ASSOC_RIGHT
)

type operator struct {
	prec  int
	assoc association
	unary bool
}

var allOperators = map[tokenType]operator{
	// Assignment operators
	EQ:     {0, ASSOC_RIGHT, false}, // =
	ADD_EQ: {0, ASSOC_RIGHT, false}, // +=
	SUB_EQ: {0, ASSOC_RIGHT, false}, // -=
	DIV_EQ: {0, ASSOC_RIGHT, false}, // /=
	MUL_EQ: {0, ASSOC_RIGHT, false}, // *=
	POW_EQ: {0, ASSOC_RIGHT, false}, // **=
	REM_EQ: {0, ASSOC_RIGHT, false}, // %=
	AND_EQ: {0, ASSOC_RIGHT, false}, // &=
	OR_EQ:  {0, ASSOC_RIGHT, false}, // |=
	XOR_EQ: {0, ASSOC_RIGHT, false}, // ^=
	LSH_EQ: {0, ASSOC_RIGHT, false}, // <<=
	RSH_EQ: {0, ASSOC_RIGHT, false}, // >>=

	// Relational operators
	EQ_EQ: {0, ASSOC_RIGHT, false}, // ==
	GT:    {0, ASSOC_RIGHT, false}, // >
	GT_EQ: {0, ASSOC_RIGHT, false}, // >=
	LT:    {0, ASSOC_RIGHT, false}, // <
	LT_EQ: {0, ASSOC_RIGHT, false}, // <=

	// Bitwise operators
	OR:  {1, ASSOC_RIGHT, false}, // |
	XOR: {2, ASSOC_RIGHT, false}, // ^
	AND: {3, ASSOC_RIGHT, false}, // &
	LSH: {4, ASSOC_RIGHT, false}, // <<
	RSH: {4, ASSOC_RIGHT, false}, // >>
	NOT: {8, ASSOC_LEFT, true},   // ~

	// Mathematical operators
	ADD:       {5, ASSOC_LEFT, false}, // +
	SUB:       {5, ASSOC_LEFT, false}, // -
	MUL:       {6, ASSOC_LEFT, false}, // *
	DIV:       {6, ASSOC_LEFT, false}, // /
	POW:       {7, ASSOC_LEFT, false}, // **
	REM:       {6, ASSOC_LEFT, false}, // %
	UNARY_MIN: {9, ASSOC_LEFT, true},  // -
}

var (
	errDivionByZero         = errors.New("Divison by zero")
	errUnmatchedParentheses = errors.New("Unmatched parentheses")
	errInvalidSyntax        = errors.New("Invalid syntax")
)

// Determine if operator 1 has higher precendence than operator 2
func (o1 operator) hasHigherPrecThan(o2 operator) bool {
	return (o2.assoc == ASSOC_LEFT && o2.prec <= o1.prec) ||
		(o2.assoc == ASSOC_RIGHT && o2.prec < o1.prec)
}

// Some useful predefined variables that can be used in expressions. These
// can be overwritten.
var constants = map[string]float64{
	"pi":  math.Pi,
	"tau": math.Pi / 2,
	"phi": math.Phi,
	"e":   math.E,
}

// New initializes a new Parser instance, useful when you want to run multiple
// expression and/or use variables.
func New() *Parser {
	return &Parser{
		pos:       0,
		Variables: constants,
	}
}

// Eval evaluates an expression and returns its result and any errors found.
//
// Example:
//     res, err := mathcat.Eval("2 * 2 * 2") // 8
func Eval(expr string) (float64, error) {
	tokens, err := Lex(expr)

	// If a lexer error occured don't parse
	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	return p.parse()
}

// Run executes an expression on an existing parser instance. Useful for
// variable assignment.
//
// Example:
//     p.Run("a = 555")
//     p.Run("a += 45")
//     res, err := p.Run("a + a") // 1200
func (p *Parser) Run(expr string) (float64, error) {
	tokens, err := Lex(expr)

	if err != nil {
		return -1, err
	}

	p.reset()
	p.tokens = tokens

	return p.parse()
}

// Exec executes an expression with a given map of variables.
//
// Example:
//     res, err := mathcat.Exec("a + b * b", map[string]float64{
//	       "a": 1,
//         "b": 3,
//     }) // 10
func Exec(expr string, vars map[string]float64) (float64, error) {
	tokens, err := Lex(expr)

	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	isValidIdent := func(c rune) bool { return isIdent(c) || isNumber(c) }

	for k, v := range vars {
		if !isIdent(rune(k[0])) || strings.IndexFunc(k, isValidIdent) == -1 {
			return -1, fmt.Errorf("Invalid variable name: '%s'")
		}
		p.Variables[k] = v
	}

	p.tokens = tokens

	return p.parse()
}

// GetVar gets an existing variable.
func (p *Parser) GetVar(index string) (float64, error) {
	if val, ok := p.Variables[index]; ok {
		return val, nil
	}

	return -1, fmt.Errorf("Undefined variable '%s'", index)
}

func (p *Parser) parse() (float64, error) {
	var (
		operands, operators stack
		o1, o2              operator
	)

	p.tok = p.tokens[0]

	for p.eat().Type != EOL {
		switch {
		case p.tok.IsLiteral():
			operands.Push(p.tok)
		case p.tok.Type == LPAREN:
			operators.Push(p.tok)
		case p.tok.IsOperator():
			o1 = allOperators[p.tok.Type]

			if !operators.Empty() {
				var ok bool
				if o2, ok = allOperators[operators.Top().(*token).Type]; !ok {
					operators.Push(p.tok)
					break
				}

				if o2.hasHigherPrecThan(o1) {
					operator := operators.Pop().(*token)
					val, err := p.evaluate(operator, &operands)
					if err != nil {
						return -1, err
					}
					operands.Push(val)
				}
			}
			operators.Push(p.tok)
		case p.tok.Type == RPAREN:
			for {
				if operators.Empty() {
					return -1, errUnmatchedParentheses
				}

				operator := operators.Pop().(*token)
				if operator.Type == LPAREN {
					break
				}
				val, err := p.evaluate(operator, &operands)
				if err != nil {
					return -1, err
				}
				operands.Push(val)
			}
		}
	}

	// Evaluate remaing operators
	for !operators.Empty() {
		operator := operators.Pop().(*token)

		if operator.Type == LPAREN {
			return -1, errUnmatchedParentheses
		}

		if operands.Empty() {
			return -1, errInvalidSyntax
		}

		val, err := p.evaluate(operator, &operands)
		if err != nil {
			return -1, err
		}
		operands.Push(val)
	}

	// If there are no operands, the expression is useless and doesn't do
	// anything, for example `()` or an empty string
	if operands.Empty() {
		return 0, nil
	}

	// Single operand left means the expression was evaluated successful
	if len(operands) == 1 {
		return p.lookup(operands[0])
	}

	// Leftover token on operand stack indicates invalid syntax
	return -1, errInvalidSyntax
}

func (p *Parser) evaluate(operator *token, operands *stack) (float64, error) {
	var (
		result      float64
		left, right float64
		err         error
		lhsToken    interface{}
	)

	if operands.Empty() {
		return -1, fmt.Errorf("Unexpected '%s'", operator.Type)
	}

	if right, err = p.lookup(operands.Pop()); err != nil {
		return -1, err
	}

	// Unary operators have no left hand side
	if op := allOperators[operator.Type]; !op.unary {
		if operands.Empty() {
			return -1, errInvalidSyntax
		}
		// Save the token in case of a assignment variable is used and we need to
		// save the result in a variable
		lhsToken = operands.Pop()

		// Don't lookup the left hand side if = is used so we can do initial
		// assignment
		if operator.Type != EQ {
			left, err = p.lookup(lhsToken)
			if err != nil {
				return -1, err
			}
		}
	}

	result, err = execute(operator, left, right)
	if err != nil {
		return -1, err
	}

	switch operator.Type {
	case EQ, ADD_EQ, SUB_EQ, DIV_EQ, MUL_EQ, POW_EQ, REM_EQ, AND_EQ, OR_EQ, XOR_EQ, LSH_EQ, RSH_EQ:
		// Save result in variable
		if lhsToken.(*token).Type != IDENT {
			return -1, errors.New("Can't assign to literal")
		}
		p.Variables[lhsToken.(*token).Value] = result
	}

	return result, nil
}

func execute(operator *token, lhs, rhs float64) (float64, error) {
	var result float64

	// Both lhs and rhs have to be whole numbers for bitwise operations
	if operator.IsBitwise() && (!IsWholeNumber(lhs) || !IsWholeNumber(rhs)) {
		return -1, fmt.Errorf("Unsupported type (float) for '%s'", operator.Type)
	}

	switch operator.Type {
	case ADD, ADD_EQ:
		result = lhs + rhs
	case SUB, SUB_EQ:
		result = lhs - rhs
	case UNARY_MIN:
		result = -rhs
	case DIV, DIV_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = lhs / rhs
	case MUL, MUL_EQ:
		result = lhs * rhs
	case POW, POW_EQ:
		result = math.Pow(lhs, rhs)
	case REM, REM_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = math.Mod(lhs, rhs)
	case AND, AND_EQ:
		result = float64(int64(lhs) & int64(rhs))
	case OR, OR_EQ:
		result = float64(int64(lhs) | int64(rhs))
	case XOR, XOR_EQ:
		result = float64(int64(lhs) ^ int64(rhs))
	case LSH, LSH_EQ:
		result = float64(uint64(lhs) << uint64(rhs))
	case RSH, RSH_EQ:
		result = float64(uint64(lhs) >> uint64(rhs))
	case NOT:
		result = float64(^int64(rhs))
	case EQ:
		result = rhs
	case EQ_EQ:
		result = bool2float(lhs == rhs)
	case GT:
		result = bool2float(lhs > rhs)
	case GT_EQ:
		result = bool2float(lhs >= rhs)
	case LT:
		result = bool2float(lhs < rhs)
	case LT_EQ:
		result = bool2float(lhs <= rhs)
	default:
		return -1, fmt.Errorf("Invalid operator '%s'", operator.Type)
	}

	return result, nil
}

// Look up a literal. If it's an identifier, check the parser's variables map,
// otherwise convert the tokenized string to a float64.
func (p *Parser) lookup(val interface{}) (float64, error) {
	// val can be a token or a float64, if it's a float64 it has been already
	// evaluated and we don't need to do anything
	if v, ok := val.(float64); ok {
		return v, nil
	}

	tok := val.(*token)
	switch tok.Type {
	case NUMBER:
		return strconv.ParseFloat(tok.Value, 64)
	case IDENT:
		res, err := p.GetVar(tok.Value)
		if err != nil {
			return -1, err
		}

		return res, nil
	}

	return -1, fmt.Errorf("Invalid lookup type: %s", tok.Type)
}

func (p *Parser) reset() {
	p.tokens = nil
	p.pos = 0
}

func (p *Parser) peek() *token {
	return p.tokens[p.pos]
}

func (p *Parser) eat() *token {
	p.tok = p.peek()
	p.pos++
	return p.tok
}

// IsWholeNumber checks if a float is a whole number
func IsWholeNumber(n float64) bool {
	epsilon := 1e-9
	_, frac := math.Modf(math.Abs(n))

	return frac < epsilon || frac > 1.0-epsilon
}

func bool2float(b bool) float64 {
	if b {
		return 1
	}
	return 0
}
<|endoftext|>


<commit_before>package ll

import (
	"errors"
	"fmt"
)

type Parser interface {
	Parse()
}

type ListParser struct {
	lexer  Lexer
	tokens []*Token
	k      int
	p      int
}

func NewListParser(lexer Lexer, k int) *ListParser {
	parser := &ListParser{
		lexer:  lexer,
		tokens: make([]*Token, k),
		k:      k,
		p:      0,
	}

	parser.init()

	return parser
}

func (l *ListParser) Parse() {
	l.list()
}

func (l *ListParser) list() {
	l.match(LBRACK)
	l.elements()
	l.match(RBRACK)
}

func (l *ListParser) match(x int) {
	if l.lookahead(1).typ != x {
		errors.New(fmt.Sprintf("unexpecting found %s \n", l.lookahead(1)))
	}

	l.consume()
}

func (l *ListParser) elements() {
	l.element()
	for l.lookahead(1).typ == COMMA {
		l.match(COMMA)
		l.element()
	}
}

func (l *ListParser) element() {
	if l.lookahead(1).typ == NAME && l.lookahead(2).typ == EQUAL {
		l.match(NAME)
		l.match(EQUAL)
		l.match(NAME)
	} else if l.lookahead(1).typ == NAME {
		l.match(NAME)
	} else if l.lookahead(1).typ == LBRACK {
		l.list()
	} else {
		errors.New(fmt.Sprintf("expecting name or list; found %s \n", l.lookahead(1).text))
	}
}

func (l *ListParser) init() {
	for i := 1; i <= l.k; i++ {
		l.consume()
	}
}

func (l *ListParser) lookahead(i int) *Token {
	return l.tokens[(l.p+i-1)%l.k]
}

func (l *ListParser) consume() {
	l.tokens[l.p] = l.lexer.NextToken()
	l.p = (l.p + 1) % l.k
}
<commit_msg>multiple if/else be replaced with switch.<commit_after>package ll

import (
	"errors"
	"fmt"
)

type Parser interface {
	Parse()
}

type ListParser struct {
	lexer  Lexer
	tokens []*Token
	k      int
	p      int
}

func NewListParser(lexer Lexer, k int) *ListParser {
	parser := &ListParser{
		lexer:  lexer,
		tokens: make([]*Token, k),
		k:      k,
		p:      0,
	}

	parser.init()

	return parser
}

func (l *ListParser) Parse() {
	l.list()
}

func (l *ListParser) list() {
	l.match(LBRACK)
	l.elements()
	l.match(RBRACK)
}

func (l *ListParser) match(x int) {
	if l.lookahead(1).typ != x {
		errors.New(fmt.Sprintf("unexpecting found %s \n", l.lookahead(1)))
	}

	l.consume()
}

func (l *ListParser) elements() {
	l.element()
	for l.lookahead(1).typ == COMMA {
		l.match(COMMA)
		l.element()
	}
}

func (l *ListParser) element() {
	switch {
	case l.lookahead(1).typ == NAME && l.lookahead(2).typ == EQUAL:
		l.match(NAME)
		l.match(EQUAL)
		l.match(NAME)
	case l.lookahead(1).typ == NAME:
		l.match(NAME)
	case l.lookahead(1).typ == LBRACK:
		l.list()
	default:
		errors.New(fmt.Sprintf("expecting name or list; found %s \n", l.lookahead(1).text))
	}
}

func (l *ListParser) init() {
	for i := 1; i <= l.k; i++ {
		l.consume()
	}
}

func (l *ListParser) lookahead(i int) *Token {
	return l.tokens[(l.p+i-1)%l.k]
}

func (l *ListParser) consume() {
	l.tokens[l.p] = l.lexer.NextToken()
	l.p = (l.p + 1) % l.k
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"

	. "goprotobuf.googlecode.com/hg/compiler/descriptor"
	"goprotobuf.googlecode.com/hg/proto"
)

func ParseFiles(filenames []string) (*FileDescriptorSet, os.Error) {
	fds := &FileDescriptorSet{
		File: make([]*FileDescriptorProto, len(filenames)),
	}

	for i, filename := range filenames {
		var err os.Error
		fds.File[i], err = parseFile(filename)
		if err != nil {
			return nil, err
		}
	}

	return fds, nil
}

func parseFile(filename string) (*FileDescriptorProto, os.Error) {
	fd := &FileDescriptorProto{
		Name: proto.String(filename),
	}

	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	// TODO
	_ = buf
	return fd, nil
}
<commit_msg>Some parsing infrastructure; enough to parse the 'package foo;' line.<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"

	. "goprotobuf.googlecode.com/hg/compiler/descriptor"
	"goprotobuf.googlecode.com/hg/proto"
)

func ParseFiles(filenames []string) (*FileDescriptorSet, os.Error) {
	fds := &FileDescriptorSet{
		File: make([]*FileDescriptorProto, len(filenames)),
	}

	for i, filename := range filenames {
		fds.File[i] = &FileDescriptorProto{
			Name: proto.String(filename),
		}
		buf, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}

		p := newParser(string(buf))
		if pe := p.readFile(fds.File[i]); pe != nil {
			return nil, pe
		}
	}

	return fds, nil
}

type parseError struct {
	message string
	line    int // 1-based line number
	offset  int // 0-based byte offset from start of input
}

func (pe *parseError) String() string {
	if pe.line == 1 {
		return fmt.Sprintf("line 1.%d: %v", pe.offset, pe.message)
	}
	return fmt.Sprintf("line %d: %v", pe.line, pe.message)
}

type token struct {
	value        string
	err          *parseError
	line, offset int
}

type parser struct {
	s            string // remaining input
	done         bool   // whether the parsing is finished
	backed       bool   // whether back() was called
	offset, line int
	cur          token
}

func newParser(s string) *parser {
	return &parser{
		s:    s,
		line: 1,
		cur: token{
			line: 1,
		},
	}
}

func (p *parser) readFile(fd *FileDescriptorProto) *parseError {
	// Read package
	if err := p.readToken("package"); err != nil {
		return err
	}
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	// TODO: check for a good package name
	fd.Package = proto.String(tok.value)
	if err := p.readToken(";"); err != nil {
		return err
	}

	// TODO: more

	return nil
}

func (p *parser) readToken(expected string) *parseError {
	tok := p.next()
	if tok.err != nil {
		return tok.err
	}
	if tok.value != expected {
		return p.error("expected %q, found %q", expected, tok.value)
	}
	return nil
}

// Back off the parser by one token; may only be done between calls to next().
func (p *parser) back() {
	p.backed = true
}

// Advances the parser and returns the new current token.
func (p *parser) next() *token {
	if p.backed || p.done {
		p.backed = false
		return &p.cur
	}
	p.advance()
	if p.done {
		p.cur.value = ""
	}
	return &p.cur
}

func (p *parser) advance() {
	// Skip whitespace
	p.skipWhitespaceAndComments()
	if p.done {
		return
	}

	// Start of non-whitespace
	p.cur.err = nil
	p.cur.offset, p.cur.line = p.offset, p.line
	switch p.s[0] {
	// TODO: more cases, like punctuation.
	case ';':
		// Single symbol
		p.cur.value, p.s = p.s[:1], p.s[1:]
	default:
		i := 0
		for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
			i++
		}
		if i == 0 {
			p.error("unexpected byte %#x", p.s[0])
			return
		}
		p.cur.value, p.s = p.s[:i], p.s[i:]
	}
	p.offset += len(p.cur.value)
}

func (p *parser) skipWhitespaceAndComments() {
	i := 0
	for i < len(p.s) {
		if isWhitespace(p.s[i]) {
			if p.s[i] == '\n' {
				p.line++
			}
			i++
			continue
		}
		if i+1 < len(p.s) && p.s[i] == '/' && p.s[i+1] == '/' {
			// comment; skip to end of line or input
			for i < len(p.s) && p.s[i] != '\n' {
				i++
			}
			if i < len(p.s) {
				// end of line; keep going
				p.line++
				continue
			}
			// end of input; fall out of loop
		}
		break
	}
	p.offset += i
	p.s = p.s[i:]
	if len(p.s) == 0 {
		p.done = true
	}
}

func (p *parser) error(format string, a ...interface{}) *parseError {
	pe := &parseError{
		message: fmt.Sprintf(format, a...),
		line:    p.cur.line,
		offset:  p.cur.offset,
	}
	p.cur.err = pe
	p.done = true
	return pe
}

func isWhitespace(c byte) bool {
	// TODO: do better
	return c == ' '
}

// Numbers and identifiers are matched by [-+._A-Za-z0-9]
func isIdentOrNumberChar(c byte) bool {
	switch {
	case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
		return true
	case '0' <= c && c <= '9':
		return true
	}
	switch c {
	case '-', '+', '.', '_':
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package fedach

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"strconv"
	"strings"
)

// Unmarshal parses the Fed-format-encoded data and stores the result in the value
// pointed to by v.
// If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
func Unmarshal(data []byte, v interface{}) error {
	reader := bytes.NewBuffer(data)

	switch reflect.TypeOf(v).String() {
	case "*[][]string":
		records := [][]string{}
		SampleRecord := RoutingDirectoryRecord{}
		for {
			line, err := reader.ReadString('\n')

			if len(line) == 0 {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}

			record := []string{}

			t := reflect.TypeOf(&SampleRecord).Elem()
			for i := 0; i < t.NumField(); i++ {
				pos := t.Field(i).Tag.Get("pos")
				indexes := strings.Split(pos, "-")

				start, _ := strconv.ParseInt(indexes[0], 10, 64)

				var end int64
				if len(indexes) == 2 {
					end, _ = strconv.ParseInt(indexes[1], 10, 64)
				} else {
					end = start
				}

				record = append(record, line[start-1:end])
			}
			records = append(records, record)
			if err != nil {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}
		}
	case "*[]fedach.RoutingDirectoryRecord":
		records := []RoutingDirectoryRecord{}
		for {
			line, err := reader.ReadString('\n')

			if len(line) == 0 {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}

			record := RoutingDirectoryRecord{}
			t := reflect.TypeOf(&record).Elem()
			for i := 0; i < t.NumField(); i++ {
				pos := t.Field(i).Tag.Get("pos")
				indexes := strings.Split(pos, "-")

				start, _ := strconv.ParseInt(indexes[0], 10, 64)

				var end int64
				if len(indexes) == 2 {
					end, _ = strconv.ParseInt(indexes[1], 10, 64)
				} else {
					end = start
				}

				value := reflect.ValueOf(line[start-1 : end])
				reflect.ValueOf(&record).Elem().Field(i).Set(value)
			}
			records = append(records, record)
			if err != nil {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}
		}
	default:
		return fmt.Errorf("Can't Unmarshal to %s, use *[][]string or *[]fedach.RoutingDirectoryRecord ", reflect.TypeOf(v).String())
	}
}

// Marshal returns the Fed file encoding of v.
func Marshal(v interface{}) (bs []byte, err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			} else if s, ok := r.(string); ok {
				err = errors.New(s)
			} else {
				err = r.(error)
			}
		}
	}()

	var records Records
	bs = records.bytes(v, records)
	return bs, err
}

// Records is an array of records from a Fed file.
type Records []byte

func (r *Records) bytes(input interface{}, records Records) []byte {
	v := reflect.ValueOf(input)
	var routingDirectoryFileBuf bytes.Buffer

	switch v.Type().String() {
	case "[]fedach.RoutingDirectoryRecord":
		for _, record := range v.Interface().([]RoutingDirectoryRecord) {
			// fmt.Printf("%s\n", record.Bytes())
			routingDirectoryFileBuf.Write(record.Bytes())
		}
	case "[][]string":
		records := make([]RoutingDirectoryRecord, 0, len(input.([][]string)))

		for _, recordLine := range input.([][]string) {
			record := RoutingDirectoryRecord{}
			for i, field := range recordLine {
				value := reflect.ValueOf(field)
				reflect.ValueOf(&record).Elem().Field(i).Set(value)
			}
			records = append(records, record)
		}
		for i, record := range records {
			// fmt.Printf("%s\n", record.Bytes())
			routingDirectoryFileBuf.Write(record.Bytes())
			if i < len(input.([][]string)) {
				routingDirectoryFileBuf.WriteByte(byte('\n'))
			}
		}
	default:
		panic("Cannot marshal provided struct.")
	}

	return routingDirectoryFileBuf.Bytes()
}
<commit_msg>Marshal: Fix typo.<commit_after>package fedach

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"strconv"
	"strings"
)

// Unmarshal parses the Fed-format-encoded data and stores the result in the value
// pointed to by v.
// If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
func Unmarshal(data []byte, v interface{}) error {
	reader := bytes.NewBuffer(data)

	switch reflect.TypeOf(v).String() {
	case "*[][]string":
		records := [][]string{}
		SampleRecord := RoutingDirectoryRecord{}
		for {
			line, err := reader.ReadString('\n')

			if len(line) == 0 {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}

			record := []string{}

			t := reflect.TypeOf(&SampleRecord).Elem()
			for i := 0; i < t.NumField(); i++ {
				pos := t.Field(i).Tag.Get("pos")
				indexes := strings.Split(pos, "-")

				start, _ := strconv.ParseInt(indexes[0], 10, 64)

				var end int64
				if len(indexes) == 2 {
					end, _ = strconv.ParseInt(indexes[1], 10, 64)
				} else {
					end = start
				}

				record = append(record, line[start-1:end])
			}
			records = append(records, record)
			if err != nil {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}
		}
	case "*[]fedach.RoutingDirectoryRecord":
		records := []RoutingDirectoryRecord{}
		for {
			line, err := reader.ReadString('\n')

			if len(line) == 0 {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}

			record := RoutingDirectoryRecord{}
			t := reflect.TypeOf(&record).Elem()
			for i := 0; i < t.NumField(); i++ {
				pos := t.Field(i).Tag.Get("pos")
				indexes := strings.Split(pos, "-")

				start, _ := strconv.ParseInt(indexes[0], 10, 64)

				var end int64
				if len(indexes) == 2 {
					end, _ = strconv.ParseInt(indexes[1], 10, 64)
				} else {
					end = start
				}

				value := reflect.ValueOf(line[start-1 : end])
				reflect.ValueOf(&record).Elem().Field(i).Set(value)
			}
			records = append(records, record)
			if err != nil {
				reflect.ValueOf(v).Elem().Set(reflect.ValueOf(records))
				return nil
			}
		}
	default:
		return fmt.Errorf("Can't Unmarshal to %s, use *[][]string or *[]fedach.RoutingDirectoryRecord ", reflect.TypeOf(v).String())
	}
}

// Marshal returns the Fed file encoding of v.
func Marshal(v interface{}) (bs []byte, err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			} else if s, ok := r.(string); ok {
				err = errors.New(s)
			} else {
				err = r.(error)
			}
		}
	}()

	var records Records
	bs = records.bytes(v, records)
	return bs, err
}

// Records is an array of records from a Fed file.
type Records []byte

func (r *Records) bytes(input interface{}, records Records) []byte {
	v := reflect.ValueOf(input)
	var routingDirectoryFileBuf bytes.Buffer

	switch v.Type().String() {
	case "[]fedach.RoutingDirectoryRecord":
		for _, record := range v.Interface().([]RoutingDirectoryRecord) {
			// fmt.Printf("%s\n", record.Bytes())
			routingDirectoryFileBuf.Write(record.Bytes())
		}
	case "[][]string":
		records := make([]RoutingDirectoryRecord, 0, len(input.([][]string)))

		for _, recordLine := range input.([][]string) {
			record := RoutingDirectoryRecord{}
			for i, field := range recordLine {
				value := reflect.ValueOf(field)
				reflect.ValueOf(&record).Elem().Field(i).Set(value)
			}
			records = append(records, record)
		}
		for _, record := range records {
			// fmt.Printf("%s\n", record.Bytes())
			routingDirectoryFileBuf.Write(record.Bytes())
		}
	default:
		panic("Cannot marshal provided struct.")
	}

	return routingDirectoryFileBuf.Bytes()
}
<|endoftext|>


<commit_before>package main

import (

	"bufio"
	"fmt"
	"os"
	"regexp"

)

type Template struct {
	Name string
	Extensions []string
	Structures map[string]string
	Types map[string]string
	Names map[string]string
	Keywords map[string]string
	Expressions map[string]string
	Libraries map[string]string
}

func templateParse(templatePath string) map[string]*Template {

	count := 0

	files   := getFiles(templatePath)
	r, _    := regexp.Compile("^templates/\\w+\\.template$")
	skip, _ := regexp.Compile("^templates/example\\.template$")

	for _, file := range files {
		// XXX
		if(r.MatchString(file) && ! skip.MatchString(file)) {
			count++
			fmt.Println("found a specific template:", file)
		}
	}
	// XXX fix handling count
	templates := map[string]*Template{}

	fmt.Println("found a few templates:", count)

	for _, file := range files {
		// XXX
		if(r.MatchString(file) && ! skip.MatchString(file)) {
			t := templateLoad(file)
			templates[t.Name] = t
		}
	}

	return templates

}

func templateLoad(templateFile string) *Template {

	t := new(Template)
	t.Name = templateFile

	sectionr, _ := regexp.Compile("^[\\w\\s]+\\:$")
	//cleanr, _   := regexp.Compile("[^\\w+]")
	//paramr, _   := regexp.Compile("^\\s+(\\w+)\\: (.*)$")

	file, err := os.Open(templateFile)
	check(err)
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if(sectionr.MatchString(scanner.Text())) {
			section := scanner.Text()[:len(scanner.Text())-1]
			fmt.Println("found section", section, "from file", templateFile)
		} else {
			parts := regexp.MustCompile(": ").Split(scanner.Text(), 2)
			if(len(parts) > 1) {
				fmt.Println("adding content match", parts[1], "to param", parts[0])
			} else {
				if(len(parts[0]) > 0) {
					fmt.Println("adding single param", parts[0])
				} else {
					//fmt.Println("skipping blank line", parts[0])
				}
			}
		}
	}

	if err := scanner.Err(); err != nil {
		check(err)
	}

	//fmt.Printf("template has this struct: %v\n", t)

	return t

}
<commit_msg>pomo3 clean up params<commit_after>package main

import (

	"bufio"
	"fmt"
	"os"
	"regexp"

)

type Template struct {
	Name string
	Extensions []string
	Structures map[string]string
	Types map[string]string
	Names map[string]string
	Keywords map[string]string
	Expressions map[string]string
	Libraries map[string]string
}

func templateParse(templatePath string) map[string]*Template {

	count := 0

	files   := getFiles(templatePath)
	r, _    := regexp.Compile("^templates/\\w+\\.template$")
	skip, _ := regexp.Compile("^templates/example\\.template$")

	for _, file := range files {
		// XXX
		if(r.MatchString(file) && ! skip.MatchString(file)) {
			count++
			fmt.Println("found a specific template:", file)
		}
	}
	// XXX fix handling count
	templates := map[string]*Template{}

	fmt.Println("found a few templates:", count)

	for _, file := range files {
		// XXX
		if(r.MatchString(file) && ! skip.MatchString(file)) {
			t := templateLoad(file)
			templates[t.Name] = t
		}
	}

	return templates

}

func templateLoad(templateFile string) *Template {

	t := new(Template)
	t.Name = templateFile

	sectionr, _ := regexp.Compile("^[\\w\\s]+\\:$")
	cleanr, _   := regexp.Compile("^\\s*")
	//paramr, _   := regexp.Compile("^\\s+(\\w+)\\: (.*)$")

	file, err := os.Open(templateFile)
	check(err)
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if(sectionr.MatchString(scanner.Text())) {
			section := scanner.Text()[:len(scanner.Text())-1]
			fmt.Println("found section", section, "from file", templateFile)
		} else {
			parts := regexp.MustCompile(": ").Split(scanner.Text(), 2)
			param := cleanr.ReplaceAllString(parts[0], "")
			if(len(parts) > 1) {
				fmt.Println("adding content match", parts[1], "to param", param)
			} else {
				if(len(param) > 0) {
					fmt.Println("adding single param", param)
				} else {
					//fmt.Println("skipping blank line", param)
				}
			}
		}
	}

	if err := scanner.Err(); err != nil {
		check(err)
	}

	//fmt.Printf("template has this struct: %v\n", t)

	return t

}
<|endoftext|>


<commit_before>package rdbtools

import (
	"bufio"
	"encoding/binary"
	"errors"
	"io"
	"math"
	"strconv"
)

type Parser struct {
	ctx ParserContext
	r   io.Reader
}

const (
	RedisRdbVersion = 6
)

var (
	errNoMoreDatabases               = errors.New("errNoMoreDatabases")
	errNoMoreKeyValuePair            = errors.New("errNoMoreKeyValuePair")
	ErrInvalidMagicString            = errors.New("invalid magic string")
	ErrInvalidRDBVersionNumber       = errors.New("invalid RDB version number")
	ErrUnexpectedEncodedLength       = errors.New("unexpected encoded length")
	ErrUnknownValueType              = errors.New("unknown value type")
	ErrUnknownLengthEncoding         = errors.New("unknown length encoding")
	ErrUnexpectedPrevLengthEntryByte = errors.New("unexpected prev length entry byte")
)

type ParserContext struct {
	DbCh                chan int
	StringObjectCh      chan StringObject
	ListMetadataCh      chan ListMetadata
	ListDataCh          chan interface{}
	SetMetadataCh       chan SetMetadata
	SetDataCh           chan interface{}
	HashMetadataCh      chan HashMetadata
	HashDataCh          chan HashEntry
	SortedSetMetadataCh chan SortedSetMetadata
	SortedSetEntriesCh  chan SortedSetEntry
	endOfFileCh         chan struct{}
}

func (c *ParserContext) closeChannels() {
	if c.DbCh != nil {
		close(c.DbCh)
	}
	if c.StringObjectCh != nil {
		close(c.StringObjectCh)
	}
	if c.ListMetadataCh != nil {
		close(c.ListMetadataCh)
	}
	if c.ListDataCh != nil {
		close(c.ListDataCh)
	}
	if c.SetMetadataCh != nil {
		close(c.SetMetadataCh)
	}
	if c.SetDataCh != nil {
		close(c.SetDataCh)
	}
	if c.HashMetadataCh != nil {
		close(c.HashMetadataCh)
	}
	if c.HashDataCh != nil {
		close(c.HashDataCh)
	}
	if c.SortedSetMetadataCh != nil {
		close(c.SortedSetMetadataCh)
	}
	if c.SortedSetEntriesCh != nil {
		close(c.SortedSetEntriesCh)
	}
	close(c.endOfFileCh)
}

func (c *ParserContext) Invalid() bool {
	return c.DbCh == nil && c.StringObjectCh == nil && c.ListMetadataCh == nil && c.ListDataCh == nil && c.SetMetadataCh == nil && c.SetDataCh == nil && c.HashMetadataCh == nil && c.HashDataCh == nil && c.SortedSetMetadataCh == nil && c.SortedSetEntriesCh == nil
}

func NewParser(ctx ParserContext) *Parser {
	ctx.endOfFileCh = make(chan struct{})
	return &Parser{ctx: ctx}
}

func (p *Parser) Parse(r io.Reader) (err error) {
	br := bufio.NewReader(r)

	if err = readMagicString(br); err != nil {
		return err
	}
	if err = readVersionNumber(br); err != nil {
		return err
	}
	for {
		if err = p.readDatabase(br); err != nil && err != errNoMoreDatabases {
			return err
		} else if err != nil && err == errNoMoreDatabases {
			break
		}

		for {
			if err = p.readKeyValuePair(br); err != nil && err != errNoMoreKeyValuePair {
				return err
			} else if err != nil && err == errNoMoreKeyValuePair {
				break
			}
		}
	}

	// End of file byte - we don't handle the error here because we already handled it in the loop before
	// via the Peek() call
	//
	// Also, we don't check for validity of the byte here. This is because in the loop before, we will continue to loop
	// until we find a valid 0xFE (next database) or 0xFF (end of file) byte. If the data happens to contain a wrong EOF byte,
	// the loop would just continue and error out somewhere.
	br.ReadByte()

	p.ctx.closeChannels()

	return nil
}

func readMagicString(r *bufio.Reader) error {
	data := make([]byte, 5)
	read, err := r.Read(data)
	if err != nil {
		return err
	}

	if read != 5 {
		return ErrInvalidMagicString
	}

	if string(data) != "REDIS" {
		return ErrInvalidMagicString
	}

	return nil
}

func readVersionNumber(r *bufio.Reader) error {
	data := make([]byte, 4)
	read, err := r.Read(data)
	if err != nil {
		return err
	}

	if read != 4 {
		return ErrInvalidRDBVersionNumber
	}

	val := string(data)
	ival, err := strconv.Atoi(val)
	if err != nil {
		return err
	}

	if ival < 1 || ival > RedisRdbVersion {
		return ErrInvalidRDBVersionNumber
	}

	return nil
}

func (p *Parser) readDatabase(r *bufio.Reader) error {
	data, err := r.Peek(1)
	if err != nil {
		return err
	}

	if data[0] != 0xFE {
		return errNoMoreDatabases
	} else {
		r.ReadByte() // Discard
	}

	var dbNumber uint8
	if err := binary.Read(r, binary.BigEndian, &dbNumber); err != nil {
		return err
	}

	if p.ctx.DbCh != nil {
		p.ctx.DbCh <- int(dbNumber)
	}

	return nil
}

func readLen(r *bufio.Reader) (int64, bool, error) {
	b, err := r.ReadByte()
	if err != nil {
		return -1, false, err
	}

	bits := (b & 0xC0) >> 6
	switch bits {
	case 0:
		return int64(b) & 0x3f, false, nil
	case 1:
		newB, err := r.ReadByte()
		if err != nil {
			return -1, false, err
		}
		return int64((int64(b)&0x3f)<<8) | int64(newB), false, nil
	case 2:
		var tmp uint32
		if err := binary.Read(r, binary.BigEndian, &tmp); err != nil {
			return -1, false, err
		}

		return int64(tmp), false, nil
	default:
		return int64(b) & 0x3f, true, nil
	}
}

func readDoubleValue(r *bufio.Reader) (float64, error) {
	l, err := r.ReadByte()
	if err != nil {
		return 0, err
	}

	switch l {
	case 255:
		return math.Inf(-1), nil
	case 254:
		return math.Inf(1), nil
	case 253:
		return math.NaN(), nil
	default:
		bytes, err := readBytes(r, int64(l))
		if err != nil {
			return 0, err
		}

		return strconv.ParseFloat(string(bytes), 64)
	}
}

func readBytes(r *bufio.Reader, length int64) ([]byte, error) {
	bytes := make([]byte, length)
	_, err := io.ReadFull(r, bytes)
	if err != nil {
		return nil, err
	}

	return bytes, nil
}

func readLZFString(r *bufio.Reader) ([]byte, error) {
	clen, _, err := readLen(r)
	if err != nil {
		return nil, err
	}

	ulen, _, err := readLen(r)
	if err != nil {
		return nil, err
	}

	cdata, err := readBytes(r, clen)
	if err != nil {
		return nil, err
	}

	return lzfDecompress(cdata, ulen), nil
}

func readString(r *bufio.Reader) (interface{}, error) {
	l, e, err := readLen(r)
	if err != nil {
		return nil, err
	}

	var bytes []byte
	if e {
		// Encoded string
		switch l {
		case 0: // INT8
			var i int8
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 1: // INT16
			var i int16
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 2: // INT32
			var i int32
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 3: // LZF
			bytes, err = readLZFString(r)
			if err != nil {
				return nil, err
			}
		}
	} else {
		// Length prefixed string
		bytes, err = readBytes(r, l)
		if err != nil {
			return nil, err
		}
	}

	return bytes, nil
}

func (p *Parser) readKeyValuePair(r *bufio.Reader) error {
	data, err := r.Peek(1)
	if err != nil {
		return err
	}

	if data[0] == 0xFE || data[0] == 0xFF {
		return errNoMoreKeyValuePair
	}

	b, _ := r.ReadByte() // We can't have an error here, it would have been caught in the call to Peek() above

	// Read expiry time in seconds
	var expiryTime int64 = -1
	if b == 0xFD {
		var tmp uint32
		if err := binary.Read(r, binary.LittleEndian, &tmp); err != nil {
			return err
		}
		expiryTime = int64(int64(tmp) * 1000)
	}

	// Read expiry time in milliseconds
	if b == 0xFC {
		if err := binary.Read(r, binary.LittleEndian, &expiryTime); err != nil {
			return err
		}
	}

	// If the byte was a expiry time flag, we need to reread a byte
	if b == 0xFD || b == 0xFC {
		b, err = r.ReadByte()
		if err != nil {
			return err
		}
	}

	keyStr, err := readString(r)
	if err != nil {
		return err
	}

	key := NewKeyObject(keyStr, expiryTime)

	switch b {
	case 0: // String encoding
		value, err := readString(r)
		if err != nil {
			return err
		}

		if p.ctx.StringObjectCh != nil {
			p.ctx.StringObjectCh <- StringObject{Key: key, Value: value}
		}
	case 1: // List encoding
		if err := p.readList(key, r); err != nil {
			return err
		}
	case 2: // Set encoding
		if err := p.readSet(key, r); err != nil {
			return err
		}
	case 3: // Sorted set encoding
		if err := p.readSortedSet(key, r); err != nil {
			return err
		}
	case 4: // Hash encoding
		if err := p.readHashMap(key, r); err != nil {
			return err
		}
	case 9: // Zipmap encoding
		if err := p.readZipMap(key, r); err != nil {
			return err
		}
	case 10: // Zip list encoding
		if err := p.readListInZipList(key, r); err != nil {
			return err
		}
	case 11: // int set encoding
		if err := p.readIntSet(key, r); err != nil {
			return err
		}
	case 12: // Sorted set in zip list encoding
		if err := p.readSortedSetInZipList(key, r); err != nil {
			return err
		}
	case 13: // hash map in zip list encoding
		if err := p.readHashMapInZipList(key, r); err != nil {
			return err
		}
	default:
		return ErrUnknownValueType
	}

	return nil
}
<commit_msg>Check the RDB version when handling the checksum<commit_after>package rdbtools

import (
	"bufio"
	"encoding/binary"
	"errors"
	"io"
	"math"
	"strconv"
)

type Parser struct {
	ctx ParserContext
	r   io.Reader
}

const (
	RedisRdbVersion = 6
)

var (
	errNoMoreDatabases               = errors.New("errNoMoreDatabases")
	errNoMoreKeyValuePair            = errors.New("errNoMoreKeyValuePair")
	ErrInvalidMagicString            = errors.New("invalid magic string")
	ErrInvalidRDBVersionNumber       = errors.New("invalid RDB version number")
	ErrUnexpectedEncodedLength       = errors.New("unexpected encoded length")
	ErrUnknownValueType              = errors.New("unknown value type")
	ErrUnknownLengthEncoding         = errors.New("unknown length encoding")
	ErrUnexpectedPrevLengthEntryByte = errors.New("unexpected prev length entry byte")
)

type ParserContext struct {
	DbCh                chan int
	StringObjectCh      chan StringObject
	ListMetadataCh      chan ListMetadata
	ListDataCh          chan interface{}
	SetMetadataCh       chan SetMetadata
	SetDataCh           chan interface{}
	HashMetadataCh      chan HashMetadata
	HashDataCh          chan HashEntry
	SortedSetMetadataCh chan SortedSetMetadata
	SortedSetEntriesCh  chan SortedSetEntry
	endOfFileCh         chan struct{}
}

func (c *ParserContext) closeChannels() {
	if c.DbCh != nil {
		close(c.DbCh)
	}
	if c.StringObjectCh != nil {
		close(c.StringObjectCh)
	}
	if c.ListMetadataCh != nil {
		close(c.ListMetadataCh)
	}
	if c.ListDataCh != nil {
		close(c.ListDataCh)
	}
	if c.SetMetadataCh != nil {
		close(c.SetMetadataCh)
	}
	if c.SetDataCh != nil {
		close(c.SetDataCh)
	}
	if c.HashMetadataCh != nil {
		close(c.HashMetadataCh)
	}
	if c.HashDataCh != nil {
		close(c.HashDataCh)
	}
	if c.SortedSetMetadataCh != nil {
		close(c.SortedSetMetadataCh)
	}
	if c.SortedSetEntriesCh != nil {
		close(c.SortedSetEntriesCh)
	}
	close(c.endOfFileCh)
}

func (c *ParserContext) Invalid() bool {
	return c.DbCh == nil && c.StringObjectCh == nil && c.ListMetadataCh == nil && c.ListDataCh == nil && c.SetMetadataCh == nil && c.SetDataCh == nil && c.HashMetadataCh == nil && c.HashDataCh == nil && c.SortedSetMetadataCh == nil && c.SortedSetEntriesCh == nil
}

func NewParser(ctx ParserContext) *Parser {
	ctx.endOfFileCh = make(chan struct{})
	return &Parser{ctx: ctx}
}

func (p *Parser) Parse(r io.Reader) (err error) {
	br := bufio.NewReader(r)

	if err = readMagicString(br); err != nil {
		return err
	}

	var rdbVersion int
	if rdbVersion, err = readVersionNumber(br); err != nil {
		return err
	}

	for {
		if err = p.readDatabase(br); err != nil && err != errNoMoreDatabases {
			return err
		} else if err != nil && err == errNoMoreDatabases {
			break
		}

		for {
			if err = p.readKeyValuePair(br); err != nil && err != errNoMoreKeyValuePair {
				return err
			} else if err != nil && err == errNoMoreKeyValuePair {
				break
			}
		}
	}

	// End of file byte - we don't handle the error here because we already handled it in the loop before
	// via the Peek() call
	//
	// Also, we don't check for validity of the byte here. This is because in the loop before, we will continue to loop
	// until we find a valid 0xFE (next database) or 0xFF (end of file) byte. If the data happens to contain a wrong EOF byte,
	// the loop would just continue and error out somewhere.
	br.ReadByte()

	// Read the CRC64 checksum with RDB version >= 5
	if rdbVersion >= 5 {
		var checksum uint64
		if err := binary.Read(br, binary.LittleEndian, &checksum); err != nil {
			return err
		}

		// TODO compare checksum
	}

	p.ctx.closeChannels()

	return nil
}

func readMagicString(r *bufio.Reader) error {
	data := make([]byte, 5)
	read, err := r.Read(data)
	if err != nil {
		return err
	}

	if read != 5 {
		return ErrInvalidMagicString
	}

	if string(data) != "REDIS" {
		return ErrInvalidMagicString
	}

	return nil
}

func readVersionNumber(r *bufio.Reader) (int, error) {
	data := make([]byte, 4)
	read, err := r.Read(data)
	if err != nil {
		return -1, err
	}

	if read != 4 {
		return -1, ErrInvalidRDBVersionNumber
	}

	val := string(data)
	ival, err := strconv.Atoi(val)
	if err != nil {
		return -1, err
	}

	if ival < 1 || ival > RedisRdbVersion {
		return -1, ErrInvalidRDBVersionNumber
	}

	return ival, nil
}

func (p *Parser) readDatabase(r *bufio.Reader) error {
	data, err := r.Peek(1)
	if err != nil {
		return err
	}

	if data[0] != 0xFE {
		return errNoMoreDatabases
	} else {
		r.ReadByte() // Discard
	}

	var dbNumber uint8
	if err := binary.Read(r, binary.BigEndian, &dbNumber); err != nil {
		return err
	}

	if p.ctx.DbCh != nil {
		p.ctx.DbCh <- int(dbNumber)
	}

	return nil
}

func readLen(r *bufio.Reader) (int64, bool, error) {
	b, err := r.ReadByte()
	if err != nil {
		return -1, false, err
	}

	bits := (b & 0xC0) >> 6
	switch bits {
	case 0:
		return int64(b) & 0x3f, false, nil
	case 1:
		newB, err := r.ReadByte()
		if err != nil {
			return -1, false, err
		}
		return int64((int64(b)&0x3f)<<8) | int64(newB), false, nil
	case 2:
		var tmp uint32
		if err := binary.Read(r, binary.BigEndian, &tmp); err != nil {
			return -1, false, err
		}

		return int64(tmp), false, nil
	default:
		return int64(b) & 0x3f, true, nil
	}
}

func readDoubleValue(r *bufio.Reader) (float64, error) {
	l, err := r.ReadByte()
	if err != nil {
		return 0, err
	}

	switch l {
	case 255:
		return math.Inf(-1), nil
	case 254:
		return math.Inf(1), nil
	case 253:
		return math.NaN(), nil
	default:
		bytes, err := readBytes(r, int64(l))
		if err != nil {
			return 0, err
		}

		return strconv.ParseFloat(string(bytes), 64)
	}
}

func readBytes(r *bufio.Reader, length int64) ([]byte, error) {
	bytes := make([]byte, length)
	_, err := io.ReadFull(r, bytes)
	if err != nil {
		return nil, err
	}

	return bytes, nil
}

func readLZFString(r *bufio.Reader) ([]byte, error) {
	clen, _, err := readLen(r)
	if err != nil {
		return nil, err
	}

	ulen, _, err := readLen(r)
	if err != nil {
		return nil, err
	}

	cdata, err := readBytes(r, clen)
	if err != nil {
		return nil, err
	}

	return lzfDecompress(cdata, ulen), nil
}

func readString(r *bufio.Reader) (interface{}, error) {
	l, e, err := readLen(r)
	if err != nil {
		return nil, err
	}

	var bytes []byte
	if e {
		// Encoded string
		switch l {
		case 0: // INT8
			var i int8
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 1: // INT16
			var i int16
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 2: // INT32
			var i int32
			if err = binary.Read(r, binary.LittleEndian, &i); err != nil {
				return nil, err
			}
			return i, nil
		case 3: // LZF
			bytes, err = readLZFString(r)
			if err != nil {
				return nil, err
			}
		}
	} else {
		// Length prefixed string
		bytes, err = readBytes(r, l)
		if err != nil {
			return nil, err
		}
	}

	return bytes, nil
}

func (p *Parser) readKeyValuePair(r *bufio.Reader) error {
	data, err := r.Peek(1)
	if err != nil {
		return err
	}

	if data[0] == 0xFE || data[0] == 0xFF {
		return errNoMoreKeyValuePair
	}

	b, _ := r.ReadByte() // We can't have an error here, it would have been caught in the call to Peek() above

	// Read expiry time in seconds
	var expiryTime int64 = -1
	if b == 0xFD {
		var tmp uint32
		if err := binary.Read(r, binary.LittleEndian, &tmp); err != nil {
			return err
		}
		expiryTime = int64(int64(tmp) * 1000)
	}

	// Read expiry time in milliseconds
	if b == 0xFC {
		if err := binary.Read(r, binary.LittleEndian, &expiryTime); err != nil {
			return err
		}
	}

	// If the byte was a expiry time flag, we need to reread a byte
	if b == 0xFD || b == 0xFC {
		b, err = r.ReadByte()
		if err != nil {
			return err
		}
	}

	keyStr, err := readString(r)
	if err != nil {
		return err
	}

	key := NewKeyObject(keyStr, expiryTime)

	switch b {
	case 0: // String encoding
		value, err := readString(r)
		if err != nil {
			return err
		}

		if p.ctx.StringObjectCh != nil {
			p.ctx.StringObjectCh <- StringObject{Key: key, Value: value}
		}
	case 1: // List encoding
		if err := p.readList(key, r); err != nil {
			return err
		}
	case 2: // Set encoding
		if err := p.readSet(key, r); err != nil {
			return err
		}
	case 3: // Sorted set encoding
		if err := p.readSortedSet(key, r); err != nil {
			return err
		}
	case 4: // Hash encoding
		if err := p.readHashMap(key, r); err != nil {
			return err
		}
	case 9: // Zipmap encoding
		if err := p.readZipMap(key, r); err != nil {
			return err
		}
	case 10: // Zip list encoding
		if err := p.readListInZipList(key, r); err != nil {
			return err
		}
	case 11: // int set encoding
		if err := p.readIntSet(key, r); err != nil {
			return err
		}
	case 12: // Sorted set in zip list encoding
		if err := p.readSortedSetInZipList(key, r); err != nil {
			return err
		}
	case 13: // hash map in zip list encoding
		if err := p.readHashMapInZipList(key, r); err != nil {
			return err
		}
	default:
		return ErrUnknownValueType
	}

	return nil
}
<|endoftext|>


<commit_before>package ftdi

import "errors"
import "unsafe"

// If installed on OSX using 'brew'
// ;;#cgo CFLAGS: -I/usr/local/Cellar/libftdi/1.1/include/libftdi1/
// ;;#cgo LDFLAGS: -lftdi1 -L/usr/local/Cellar/libftdi/1.1/lib/

// #cgo pkg-config: libftdi
// #include <ftdi.h>
import "C"

// Return Library version, formatted to match D2XX
func GetLibraryVersion() uint32 {
	//v := C.ftdi_get_library_version()
	//return uint32(v.major&0xFF<<16 +
	//	v.minor&0xFF<<8 +
	//	v.micro&0xFF)

	// Not implemented, so we assume version 0.19.0
	return 0x001900
}

type DeviceInfo struct {
	index         uint64
	id            uint32 // used as interface number
	serial_number string
	description   string
	manufacturer  string
	handle        unsafe.Pointer // the libusb device pointer
}

//TODO: Need to expand multi-interface devices, and then to other FTDI chips
func GetDeviceList() (dl []DeviceInfo, e error) {
	ctx := C.ftdi_new()
	defer C.ftdi_free(ctx)
	if ctx == nil {
		return nil, errors.New("Failed to create FTDI context")
	}

	var dev_list *C.struct_ftdi_device_list
	defer C.ftdi_list_free(&dev_list)

	num := C.ftdi_usb_find_all(ctx, &dev_list, 0x0403, 0x6011)
	if num < 0 {
		return nil, getErr(ctx)
	}

	dl = make([]DeviceInfo, num*4)

	for i := 0; i < int(num); i++ {

		const CHAR_SZ = 64
		var mnf_char, desc_char, ser_char [CHAR_SZ]C.char

		ret := C.ftdi_usb_get_strings(ctx, dev_list.dev,
			(*C.char)(&mnf_char[0]), CHAR_SZ,
			(*C.char)(&desc_char[0]), CHAR_SZ,
			(*C.char)(&ser_char[0]), CHAR_SZ)
		if ret != 0 {
			return nil, getErr(ctx)
		}

		var d DeviceInfo
		d.handle = unsafe.Pointer(dev_list.dev)
		d.manufacturer = C.GoString(&mnf_char[0])

		for j, intrfce := range []string{"A", "B", "C", "D"} {
			d.index = uint64(i*4 + j)
			d.id = uint32(j)
			d.description = C.GoString(&desc_char[0]) + " " + intrfce
			d.serial_number = C.GoString(&ser_char[0]) + intrfce
			dl[d.index] = d
		}
		dev_list = dev_list.next
	}

	return dl, nil
}

type Device struct {
	ctx *C.struct_ftdi_context
}

func Open(di DeviceInfo) (d *Device, e error) {
	ctx := C.ftdi_new()
	if ctx == nil {
		C.ftdi_free(ctx)
		return d, errors.New("Failed to create FTDI context")
	}

	if ret := C.ftdi_set_interface(ctx, di.id); ret != 0 {
		C.ftdi_free(ctx)
		return d, getErr(ctx)
	}

	if ret := C.ftdi_usb_open_dev(ctx, (*C.struct_usb_device)(di.handle)); ret != 0 {
		C.ftdi_free(ctx)
		return d, getErr(ctx)
	}

	return &Device{ctx}, nil
}

func (d *Device) Close() (e error) {
	defer C.ftdi_free(d.ctx)
	if ret := C.ftdi_usb_close(d.ctx); ret != 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) GetStatus() (rx_queue, tx_queue, events int32, e error) {
	return 0, 0, 0, errors.New("Not Implemented")
}

func (d *Device) Read(p []byte) (n int, e error) {
	ret := C.ftdi_read_data(d.ctx, (*C.uchar)(&p[0]), C.int(len(p)))
	if ret < 0 {
		return 0, getErr(d.ctx)
	}
	return int(ret), nil
}

func (d *Device) Write(p []byte) (n int, e error) {
	ret := C.ftdi_write_data(d.ctx, (*C.uchar)(&p[0]), C.int(len(p)))
	if ret < 0 {
		return 0, getErr(d.ctx)
	}
	return int(ret), nil
}

func (d *Device) SetBaudRate(baud uint) (e error) {
	if ret := C.ftdi_set_baudrate(d.ctx, C.int(baud)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetChars(event, err byte) (e error) {
	if ret := C.ftdi_set_event_char(d.ctx, C.uchar(event), C.uchar(event)); ret < 0 {
		return getErr(d.ctx)
	}
	if ret := C.ftdi_set_error_char(d.ctx, C.uchar(err), C.uchar(err)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetBitMode(mode BitMode) (e error) {
	const mask = 0x00
	if ret := C.ftdi_set_bitmode(d.ctx, mask, C.uchar(mode)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetFlowControl(f FlowControl) (e error) {
	if ret := C.ftdi_setflowctrl(d.ctx, C.int(f)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetLatency(latency int) (e error) {
	if ret := C.ftdi_set_latency_timer(d.ctx, C.uchar(latency)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetTransferSize(read_size, write_size int) (e error) {
	if ret := C.ftdi_read_data_set_chunksize(d.ctx, C.uint(read_size)); ret < 0 {
		return getErr(d.ctx)
	}
	if ret := C.ftdi_write_data_set_chunksize(d.ctx, C.uint(write_size)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetLineProperty(props LineProperties) (e error) {
	if ret := C.ftdi_set_line_property(d.ctx,
		uint32(props.Bits),
		uint32(props.StopBits),
		uint32(props.Parity)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetTimeout(read_timeout, write_timeout int) (e error) {
	// NOP
	return nil
}

func (d *Device) Reset() (e error) {
	if ret := C.ftdi_usb_reset(d.ctx); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) Purge() (e error) {
	if ret := C.ftdi_usb_purge_buffers(d.ctx); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func getErr(ctx *C.struct_ftdi_context) error {
	return errors.New(C.GoString(C.ftdi_get_error_string(ctx)))
}
<commit_msg>Off-by-one error in interface selection<commit_after>package ftdi

import "errors"
import "unsafe"

// If installed on OSX using 'brew'
// ;;#cgo CFLAGS: -I/usr/local/Cellar/libftdi/1.1/include/libftdi1/
// ;;#cgo LDFLAGS: -lftdi1 -L/usr/local/Cellar/libftdi/1.1/lib/

// #cgo pkg-config: libftdi
// #include <ftdi.h>
import "C"

// Return Library version, formatted to match D2XX
func GetLibraryVersion() uint32 {
	//v := C.ftdi_get_library_version()
	//return uint32(v.major&0xFF<<16 +
	//	v.minor&0xFF<<8 +
	//	v.micro&0xFF)

	// Not implemented, so we assume version 0.19.0
	return 0x001900
}

type DeviceInfo struct {
	index         uint64
	id            uint32 // used as interface number
	serial_number string
	description   string
	manufacturer  string
	handle        unsafe.Pointer // the libusb device pointer
}

//TODO: Need to expand multi-interface devices, and then to other FTDI chips
func GetDeviceList() (dl []DeviceInfo, e error) {
	ctx := C.ftdi_new()
	defer C.ftdi_free(ctx)
	if ctx == nil {
		return nil, errors.New("Failed to create FTDI context")
	}

	var dev_list *C.struct_ftdi_device_list
	defer C.ftdi_list_free(&dev_list)

	num := C.ftdi_usb_find_all(ctx, &dev_list, 0x0403, 0x6011)
	if num < 0 {
		return nil, getErr(ctx)
	}

	dl = make([]DeviceInfo, num*4)

	for i := 0; i < int(num); i++ {

		const CHAR_SZ = 64
		var mnf_char, desc_char, ser_char [CHAR_SZ]C.char

		ret := C.ftdi_usb_get_strings(ctx, dev_list.dev,
			(*C.char)(&mnf_char[0]), CHAR_SZ,
			(*C.char)(&desc_char[0]), CHAR_SZ,
			(*C.char)(&ser_char[0]), CHAR_SZ)
		if ret != 0 {
			return nil, getErr(ctx)
		}

		var d DeviceInfo
		d.handle = unsafe.Pointer(dev_list.dev)
		d.manufacturer = C.GoString(&mnf_char[0])

		for j, intrfce := range []string{"A", "B", "C", "D"} {
			d.index = uint64(i*4 + j)
			d.id = uint32(j + 1)
			d.description = C.GoString(&desc_char[0]) + " " + intrfce
			d.serial_number = C.GoString(&ser_char[0]) + intrfce
			dl[d.index] = d
		}
		dev_list = dev_list.next
	}

	return dl, nil
}

type Device struct {
	ctx *C.struct_ftdi_context
}

func Open(di DeviceInfo) (d *Device, e error) {
	ctx := C.ftdi_new()
	if ctx == nil {
		C.ftdi_free(ctx)
		return d, errors.New("Failed to create FTDI context")
	}

	if ret := C.ftdi_set_interface(ctx, di.id); ret != 0 {
		C.ftdi_free(ctx)
		return d, getErr(ctx)
	}

	if ret := C.ftdi_usb_open_dev(ctx, (*C.struct_usb_device)(di.handle)); ret != 0 {
		C.ftdi_free(ctx)
		return d, getErr(ctx)
	}

	return &Device{ctx}, nil
}

func (d *Device) Close() (e error) {
	defer C.ftdi_free(d.ctx)
	if ret := C.ftdi_usb_close(d.ctx); ret != 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) GetStatus() (rx_queue, tx_queue, events int32, e error) {
	return 0, 0, 0, errors.New("Not Implemented")
}

func (d *Device) Read(p []byte) (n int, e error) {
	ret := C.ftdi_read_data(d.ctx, (*C.uchar)(&p[0]), C.int(len(p)))
	if ret < 0 {
		return 0, getErr(d.ctx)
	}
	return int(ret), nil
}

func (d *Device) Write(p []byte) (n int, e error) {
	ret := C.ftdi_write_data(d.ctx, (*C.uchar)(&p[0]), C.int(len(p)))
	if ret < 0 {
		return 0, getErr(d.ctx)
	}
	return int(ret), nil
}

func (d *Device) SetBaudRate(baud uint) (e error) {
	if ret := C.ftdi_set_baudrate(d.ctx, C.int(baud)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetChars(event, err byte) (e error) {
	if ret := C.ftdi_set_event_char(d.ctx, C.uchar(event), C.uchar(event)); ret < 0 {
		return getErr(d.ctx)
	}
	if ret := C.ftdi_set_error_char(d.ctx, C.uchar(err), C.uchar(err)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetBitMode(mode BitMode) (e error) {
	const mask = 0x00
	if ret := C.ftdi_set_bitmode(d.ctx, mask, C.uchar(mode)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetFlowControl(f FlowControl) (e error) {
	if ret := C.ftdi_setflowctrl(d.ctx, C.int(f)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetLatency(latency int) (e error) {
	if ret := C.ftdi_set_latency_timer(d.ctx, C.uchar(latency)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetTransferSize(read_size, write_size int) (e error) {
	if ret := C.ftdi_read_data_set_chunksize(d.ctx, C.uint(read_size)); ret < 0 {
		return getErr(d.ctx)
	}
	if ret := C.ftdi_write_data_set_chunksize(d.ctx, C.uint(write_size)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetLineProperty(props LineProperties) (e error) {
	if ret := C.ftdi_set_line_property(d.ctx,
		uint32(props.Bits),
		uint32(props.StopBits),
		uint32(props.Parity)); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) SetTimeout(read_timeout, write_timeout int) (e error) {
	// NOP
	return nil
}

func (d *Device) Reset() (e error) {
	if ret := C.ftdi_usb_reset(d.ctx); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func (d *Device) Purge() (e error) {
	if ret := C.ftdi_usb_purge_buffers(d.ctx); ret < 0 {
		return getErr(d.ctx)
	}
	return nil
}

func getErr(ctx *C.struct_ftdi_context) error {
	return errors.New(C.GoString(C.ftdi_get_error_string(ctx)))
}
<|endoftext|>


<commit_before>package eval

import (
	"errors"
	"fmt"
)

var ErrArityMismatch = errors.New("arity mismatch")

var unnamedRestArg = "@"

// Closure is a closure defined in elvish script.
type Closure struct {
	ArgNames []string
	// The name for the rest argument. If empty, the function has fixed arity.
	// If equal to unnamedRestArg, the rest argument is unnamed but can be
	// accessed via $args.
	RestArg  string
	Op       Op
	Captured map[string]Variable
}

var _ FnValue = &Closure{}

func (*Closure) Kind() string {
	return "fn"
}

func newClosure(a []string, r string, op Op, e map[string]Variable) *Closure {
	return &Closure{a, r, op, e}
}

func (c *Closure) Repr(int) string {
	return fmt.Sprintf("<closure%v>", *c)
}

// Call calls a closure.
func (c *Closure) Call(ec *EvalCtx, args []Value, opts map[string]Value) {
	// TODO Support keyword arguments
	if c.RestArg != "" {
		if len(c.ArgNames) > len(args) {
			throw(ErrArityMismatch)
		}
	} else {
		if len(c.ArgNames) != len(args) {
			throw(ErrArityMismatch)
		}
	}

	// This evalCtx is dedicated to the current form, so we modify it in place.
	// BUG(xiaq): When evaluating closures, async access to global variables
	// and ports can be problematic.

	// Make upvalue namespace and capture variables.
	ec.up = make(map[string]Variable)
	for name, variable := range c.Captured {
		ec.up[name] = variable
	}
	// Make local namespace and pass arguments.
	ec.local = make(map[string]Variable)
	for i, name := range c.ArgNames {
		ec.local[name] = NewPtrVariable(args[i])
	}
	if c.RestArg != "" && c.RestArg != unnamedRestArg {
		ec.local[c.RestArg] = NewPtrVariable(NewList(args[len(c.ArgNames):]...))
	}
	Logger.Printf("EvalCtx=%p, args=%v, opts=%v", ec, args, opts)
	ec.positionals = args
	ec.local["args"] = NewPtrVariable(List{&args})
	// XXX This conversion was done by the other direction.
	convertedOpts := make(map[Value]Value)
	for k, v := range opts {
		convertedOpts[String(k)] = v
	}
	ec.local["opts"] = NewPtrVariable(Map{&convertedOpts})

	// TODO(xiaq): Also change ec.name and ec.text since the closure being
	// called can come from another source.

	c.Op.Exec(ec)
}
<commit_msg>Comment out a log.<commit_after>package eval

import (
	"errors"
	"fmt"
)

var ErrArityMismatch = errors.New("arity mismatch")

var unnamedRestArg = "@"

// Closure is a closure defined in elvish script.
type Closure struct {
	ArgNames []string
	// The name for the rest argument. If empty, the function has fixed arity.
	// If equal to unnamedRestArg, the rest argument is unnamed but can be
	// accessed via $args.
	RestArg  string
	Op       Op
	Captured map[string]Variable
}

var _ FnValue = &Closure{}

func (*Closure) Kind() string {
	return "fn"
}

func newClosure(a []string, r string, op Op, e map[string]Variable) *Closure {
	return &Closure{a, r, op, e}
}

func (c *Closure) Repr(int) string {
	return fmt.Sprintf("<closure%v>", *c)
}

// Call calls a closure.
func (c *Closure) Call(ec *EvalCtx, args []Value, opts map[string]Value) {
	// TODO Support keyword arguments
	if c.RestArg != "" {
		if len(c.ArgNames) > len(args) {
			throw(ErrArityMismatch)
		}
	} else {
		if len(c.ArgNames) != len(args) {
			throw(ErrArityMismatch)
		}
	}

	// This evalCtx is dedicated to the current form, so we modify it in place.
	// BUG(xiaq): When evaluating closures, async access to global variables
	// and ports can be problematic.

	// Make upvalue namespace and capture variables.
	ec.up = make(map[string]Variable)
	for name, variable := range c.Captured {
		ec.up[name] = variable
	}
	// Make local namespace and pass arguments.
	ec.local = make(map[string]Variable)
	for i, name := range c.ArgNames {
		ec.local[name] = NewPtrVariable(args[i])
	}
	if c.RestArg != "" && c.RestArg != unnamedRestArg {
		ec.local[c.RestArg] = NewPtrVariable(NewList(args[len(c.ArgNames):]...))
	}
	// Logger.Printf("EvalCtx=%p, args=%v, opts=%v", ec, args, opts)
	ec.positionals = args
	ec.local["args"] = NewPtrVariable(List{&args})
	// XXX This conversion was done by the other direction.
	convertedOpts := make(map[Value]Value)
	for k, v := range opts {
		convertedOpts[String(k)] = v
	}
	ec.local["opts"] = NewPtrVariable(Map{&convertedOpts})

	// TODO(xiaq): Also change ec.name and ec.text since the closure being
	// called can come from another source.

	c.Op.Exec(ec)
}
<|endoftext|>