<commit_before>package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/go-semantic-release/semantic-release/pkg/condition"
	"github.com/go-semantic-release/semantic-release/pkg/semrel"
	"github.com/go-semantic-release/semantic-release/pkg/update"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var SRVERSION string

func errorHandler(logger *log.Logger) func(error) {
	return func(err error) {
		if err != nil {
			logger.Println(err)
			os.Exit(1)
		}
	}
}

type SemRelConfig struct {
	MaintainedVersion string `json:"maintainedVersion"`
}

func loadConfig() *SemRelConfig {
	f, err := os.OpenFile(".semrelrc", os.O_RDONLY, 0)
	if err != nil {
		return &SemRelConfig{}
	}
	src := &SemRelConfig{}
	json.NewDecoder(f).Decode(src)
	f.Close()
	return src
}

func main() {
	token := flag.String("token", os.Getenv("GITHUB_TOKEN"), "github token")
	slug := flag.String("slug", condition.GetDefaultRepoSlug(), "slug of the repository")
	changelogFile := flag.String("changelog", "", "creates a changelog file")
	ghr := flag.Bool("ghr", false, "create a .ghr file with the parameters for ghr")
	noci := flag.Bool("noci", false, "run semantic-release locally")
	dry := flag.Bool("dry", false, "do not create release")
	vFile := flag.Bool("vf", false, "create a .version file")
	showVersion := flag.Bool("version", false, "outputs the semantic-release version")
	updateFile := flag.String("update", "", "updates the version of a certain file")
	gheHost := flag.String("ghe-host", os.Getenv("GITHUB_ENTERPRISE_HOST"), "github enterprise host")
	isPrerelease := flag.Bool("prerelease", false, "flags the release as a prerelease")
	isTravisCom := flag.Bool("travis-com", false, "force semantic-release to use the travis-ci.com API endpoint")
	flag.Parse()

	if *showVersion {
		fmt.Printf("semantic-release v%s", SRVERSION)
		return
	}

	logger := log.New(os.Stderr, "[semantic-release]: ", 0)
	exitIfError := errorHandler(logger)

	if val, ok := os.LookupEnv("GH_TOKEN"); *token == "" && ok {
		*token = val
	}

	if *token == "" {
		exitIfError(errors.New("github token missing"))
	}

	ci := condition.NewCI()
	logger.Printf("detected CI: %s\n", ci.Name())

	if *slug == "" {
		exitIfError(errors.New("slug missing"))
	}

	repo, err := semrel.NewRepository(context.TODO(), *gheHost, *slug, *token)
	exitIfError(err)

	logger.Println("getting default branch...")
	defaultBranch, isPrivate, err := repo.GetInfo()
	exitIfError(err)
	logger.Println("found default branch: " + defaultBranch)
	if isPrivate {
		logger.Println("repo is private")
	}

	currentBranch := ci.GetCurrentBranch()
	if currentBranch == "" {
		exitIfError(fmt.Errorf("current branch not found"))
	}
	logger.Println("found current branch: " + currentBranch)

	config := loadConfig()
	if config.MaintainedVersion != "" && currentBranch == defaultBranch {
		exitIfError(fmt.Errorf("maintained version not allowed on default branch"))
	}

	if config.MaintainedVersion != "" {
		logger.Println("found maintained version: " + config.MaintainedVersion)
		defaultBranch = "*"
	}

	currentSha := ci.GetCurrentSHA()
	logger.Println("found current sha: " + currentSha)

	if !*noci {
		logger.Println("running CI condition...")
		config := condition.CIConfig{
			"token":         *token,
			"defaultBranch": defaultBranch,
			"private":       isPrivate || *isTravisCom,
		}
		exitIfError(ci.RunCondition(config))
	}

	logger.Println("getting latest release...")
	release, err := repo.GetLatestRelease(config.MaintainedVersion)
	exitIfError(err)
	logger.Println("found version: " + release.Version.String())

	if strings.Contains(config.MaintainedVersion, "-") && release.Version.Prerelease() == "" {
		exitIfError(fmt.Errorf("no pre-release for this version possible"))
	}

	logger.Println("getting commits...")
	commits, err := repo.GetCommits(currentSha)
	exitIfError(err)

	logger.Println("calculating new version...")
	newVer := semrel.GetNewVersion(commits, release)
	if newVer == nil {
		exitIfError(errors.New("no change"))
	}
	logger.Println("new version: " + newVer.String())

	if *dry {
		exitIfError(errors.New("DRY RUN: no release was created"))
	}

	logger.Println("generating changelog...")
	changelog := semrel.GetChangelog(commits, release, newVer)
	if *changelogFile != "" {
		exitIfError(ioutil.WriteFile(*changelogFile, []byte(changelog), 0644))
	}

	logger.Println("creating release...")
	exitIfError(repo.CreateRelease(changelog, newVer, *isPrerelease, currentBranch, currentSha))

	if *ghr {
		exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
	}

	if *vFile {
		exitIfError(ioutil.WriteFile(".version", []byte(newVer.String()), 0644))
	}

	if *updateFile != "" {
		exitIfError(update.Apply(*updateFile, newVer.String()))
	}

	logger.Println("done.")
}
<commit_msg>feat: use different exit code if no release was created<commit_after>package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/go-semantic-release/semantic-release/pkg/condition"
	"github.com/go-semantic-release/semantic-release/pkg/semrel"
	"github.com/go-semantic-release/semantic-release/pkg/update"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var SRVERSION string

func errorHandler(logger *log.Logger) func(error, ...int) {
	return func(err error, exitCode ...int) {
		if err != nil {
			logger.Println(err)
			if len(exitCode) == 1 {
				os.Exit(exitCode[0])
				return
			}
			os.Exit(1)
		}
	}
}

type SemRelConfig struct {
	MaintainedVersion string `json:"maintainedVersion"`
}

func loadConfig() *SemRelConfig {
	f, err := os.OpenFile(".semrelrc", os.O_RDONLY, 0)
	if err != nil {
		return &SemRelConfig{}
	}
	src := &SemRelConfig{}
	json.NewDecoder(f).Decode(src)
	f.Close()
	return src
}

func main() {
	token := flag.String("token", os.Getenv("GITHUB_TOKEN"), "github token")
	slug := flag.String("slug", condition.GetDefaultRepoSlug(), "slug of the repository")
	changelogFile := flag.String("changelog", "", "creates a changelog file")
	ghr := flag.Bool("ghr", false, "create a .ghr file with the parameters for ghr")
	noci := flag.Bool("noci", false, "run semantic-release locally")
	dry := flag.Bool("dry", false, "do not create release")
	vFile := flag.Bool("vf", false, "create a .version file")
	showVersion := flag.Bool("version", false, "outputs the semantic-release version")
	updateFile := flag.String("update", "", "updates the version of a certain file")
	gheHost := flag.String("ghe-host", os.Getenv("GITHUB_ENTERPRISE_HOST"), "github enterprise host")
	isPrerelease := flag.Bool("prerelease", false, "flags the release as a prerelease")
	isTravisCom := flag.Bool("travis-com", false, "force semantic-release to use the travis-ci.com API endpoint")
	flag.Parse()

	if *showVersion {
		fmt.Printf("semantic-release v%s", SRVERSION)
		return
	}

	logger := log.New(os.Stderr, "[semantic-release]: ", 0)
	exitIfError := errorHandler(logger)

	if val, ok := os.LookupEnv("GH_TOKEN"); *token == "" && ok {
		*token = val
	}

	if *token == "" {
		exitIfError(errors.New("github token missing"))
	}

	ci := condition.NewCI()
	logger.Printf("detected CI: %s\n", ci.Name())

	if *slug == "" {
		exitIfError(errors.New("slug missing"))
	}

	repo, err := semrel.NewRepository(context.TODO(), *gheHost, *slug, *token)
	exitIfError(err)

	logger.Println("getting default branch...")
	defaultBranch, isPrivate, err := repo.GetInfo()
	exitIfError(err)
	logger.Println("found default branch: " + defaultBranch)
	if isPrivate {
		logger.Println("repo is private")
	}

	currentBranch := ci.GetCurrentBranch()
	if currentBranch == "" {
		exitIfError(fmt.Errorf("current branch not found"))
	}
	logger.Println("found current branch: " + currentBranch)

	config := loadConfig()
	if config.MaintainedVersion != "" && currentBranch == defaultBranch {
		exitIfError(fmt.Errorf("maintained version not allowed on default branch"))
	}

	if config.MaintainedVersion != "" {
		logger.Println("found maintained version: " + config.MaintainedVersion)
		defaultBranch = "*"
	}

	currentSha := ci.GetCurrentSHA()
	logger.Println("found current sha: " + currentSha)

	if !*noci {
		logger.Println("running CI condition...")
		config := condition.CIConfig{
			"token":         *token,
			"defaultBranch": defaultBranch,
			"private":       isPrivate || *isTravisCom,
		}
		exitIfError(ci.RunCondition(config))
	}

	logger.Println("getting latest release...")
	release, err := repo.GetLatestRelease(config.MaintainedVersion)
	exitIfError(err)
	logger.Println("found version: " + release.Version.String())

	if strings.Contains(config.MaintainedVersion, "-") && release.Version.Prerelease() == "" {
		exitIfError(fmt.Errorf("no pre-release for this version possible"))
	}

	logger.Println("getting commits...")
	commits, err := repo.GetCommits(currentSha)
	exitIfError(err)

	logger.Println("calculating new version...")
	newVer := semrel.GetNewVersion(commits, release)
	if newVer == nil {
		exitIfError(errors.New("no change"), 65)
	}
	logger.Println("new version: " + newVer.String())

	if *dry {
		exitIfError(errors.New("DRY RUN: no release was created"), 65)
	}

	logger.Println("generating changelog...")
	changelog := semrel.GetChangelog(commits, release, newVer)
	if *changelogFile != "" {
		exitIfError(ioutil.WriteFile(*changelogFile, []byte(changelog), 0644))
	}

	logger.Println("creating release...")
	exitIfError(repo.CreateRelease(changelog, newVer, *isPrerelease, currentBranch, currentSha))

	if *ghr {
		exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
	}

	if *vFile {
		exitIfError(ioutil.WriteFile(".version", []byte(newVer.String()), 0644))
	}

	if *updateFile != "" {
		exitIfError(update.Apply(*updateFile, newVer.String()))
	}

	logger.Println("done.")
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
)

func TestMain(m *testing.M) { os.Exit(m.Run()) }
<commit_msg>Added missing os package<commit_after>package main

import (
	"os"
	"testing"
)

func TestMain(m *testing.M) {
	exitCode := m.Run()
	os.Exit(exitCode)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/mondough/phosphor/internal/util"
	"github.com/mondough/phosphor/internal/version"
	"github.com/mondough/phosphor/phosphor"
	"github.com/mreiferson/go-options"
)

func phosphorFlagset() *flag.FlagSet {
	flagSet := flag.NewFlagSet("phosphor", flag.ExitOnError)

	// basic options
	flagSet.Bool("version", false, "print version string")
	flagSet.Bool("verbose", false, "enable verbose logging")
	flagSet.Int64("worker-id", 0, "unique seed for message ID generation (int) in range [0,4096) (will default to a hash of hostname)")
	flagSet.String("https-address", "", "<addr>:<port> to listen on for HTTPS clients")
	flagSet.String("http-address", "0.0.0.0:7750", "<addr>:<port> to listen on for HTTP clients")

	// NSQ Transport options
	nsqLookupdHTTPAddrs := util.StringArray{}
	flagSet.Var(&nsqLookupdHTTPAddrs, "nsqlookupd-http-address", "nsqlookupd HTTP address (may be given multiple times)")
	nsqdHTTPAddrs := util.StringArray{}
	flagSet.Var(&nsqdHTTPAddrs, "nsqd-http-address", "nsqd HTTP address (may be given multiple times)")
	flagSet.String("nsq-topic", "phosphor", "NSQ topic name to recieve traces from")
	flagSet.String("nsq-channel", "phosphor-server", "NSQ channel name to recieve traces from. This should be the same for all instances of the phosphor servers to spread ingestion work.")
	flagSet.Int("nsq-max-inflight", 200, "Number of traces to allow NSQ to keep inflight")
	flagSet.Int("nsq-num-handlers", 10, "Number of concurrent NSQ handlers to run")

	return flagSet
}

func main() {
	flagSet := phosphorFlagset()
	flagSet.Parse(os.Args[1:])

	// Globally seed rand
	rand.Seed(time.Now().UTC().UnixNano())

	if flagSet.Lookup("version").Value.(flag.Getter).Get().(bool) {
		fmt.Println(version.String("phosphor"))
		return
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	opts := phosphor.NewOptions()
	cfg := map[string]interface{}{}
	options.Resolve(opts, flagSet, cfg)

	p := phosphor.New(opts)

	p.Run()
	<-signalChan
	p.Exit()
}
<commit_msg>Minor var name tweak<commit_after>package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/mondough/phosphor/internal/util"
	"github.com/mondough/phosphor/internal/version"
	"github.com/mondough/phosphor/phosphor"
	"github.com/mreiferson/go-options"
)

func phosphorFlagSet() *flag.FlagSet {
	flagSet := flag.NewFlagSet("phosphor", flag.ExitOnError)

	// basic options
	flagSet.Bool("version", false, "print version string")
	flagSet.Bool("verbose", false, "enable verbose logging")
	flagSet.Int64("worker-id", 0, "unique seed for message ID generation (int) in range [0,4096) (will default to a hash of hostname)")
	flagSet.String("https-address", "", "<addr>:<port> to listen on for HTTPS clients")
	flagSet.String("http-address", "0.0.0.0:7750", "<addr>:<port> to listen on for HTTP clients")

	// NSQ Transport options
	nsqLookupdHTTPAddrs := util.StringArray{}
	flagSet.Var(&nsqLookupdHTTPAddrs, "nsqlookupd-http-address", "nsqlookupd HTTP address (may be given multiple times)")
	nsqdHTTPAddrs := util.StringArray{}
	flagSet.Var(&nsqdHTTPAddrs, "nsqd-http-address", "nsqd HTTP address (may be given multiple times)")
	flagSet.String("nsq-topic", "phosphor", "NSQ topic name to recieve traces from")
	flagSet.String("nsq-channel", "phosphor-server", "NSQ channel name to recieve traces from. This should be the same for all instances of the phosphor servers to spread ingestion work.")
	flagSet.Int("nsq-max-inflight", 200, "Number of traces to allow NSQ to keep inflight")
	flagSet.Int("nsq-num-handlers", 10, "Number of concurrent NSQ handlers to run")

	return flagSet
}

func main() {
	flagSet := phosphorFlagSet()
	flagSet.Parse(os.Args[1:])

	// Globally seed rand
	rand.Seed(time.Now().UTC().UnixNano())

	if flagSet.Lookup("version").Value.(flag.Getter).Get().(bool) {
		fmt.Println(version.String("phosphor"))
		return
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	opts := phosphor.NewOptions()
	cfg := map[string]interface{}{}
	options.Resolve(opts, flagSet, cfg)

	p := phosphor.New(opts)

	p.Run()
	<-signalChan
	p.Exit()
}
<|endoftext|>


<commit_before>package io

import (
	"io"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
)

type BufferedWriter struct {
	sync.Mutex
	writer io.Writer
	buffer *alloc.Buffer
	cached bool
}

func NewBufferedWriter(rawWriter io.Writer) *BufferedWriter {
	return &BufferedWriter{
		writer: rawWriter,
		buffer: alloc.NewBuffer().Clear(),
		cached: true,
	}
}

func (this *BufferedWriter) Write(b []byte) (int, error) {
	this.Lock()
	defer this.Unlock()

	if this.writer == nil {
		return 0, io.EOF
	}

	if !this.cached {
		return this.writer.Write(b)
	}
	nBytes, _ := this.buffer.Write(b)
	if this.buffer.IsFull() {
		err := this.Flush()
		if err != nil {
			return nBytes, err
		}
	}
	return nBytes, nil
}

func (this *BufferedWriter) Flush() error {
	this.Lock()
	defer this.Unlock()
	if this.writer == nil {
		return io.EOF
	}

	defer this.buffer.Clear()
	for !this.buffer.IsEmpty() {
		nBytes, err := this.writer.Write(this.buffer.Value)
		if err != nil {
			return err
		}
		this.buffer.SliceFrom(nBytes)
	}
	return nil
}

func (this *BufferedWriter) Cached() bool {
	return this.cached
}

func (this *BufferedWriter) SetCached(cached bool) {
	this.cached = cached
	if !cached && !this.buffer.IsEmpty() {
		this.Flush()
	}
}

func (this *BufferedWriter) Release() {
	this.Lock()
	defer this.Unlock()

	this.Flush()
	this.buffer.Release()
	this.buffer = nil
	this.writer = nil
}
<commit_msg>Fix dead lock in buffered writer<commit_after>package io

import (
	"io"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
)

type BufferedWriter struct {
	sync.Mutex
	writer io.Writer
	buffer *alloc.Buffer
	cached bool
}

func NewBufferedWriter(rawWriter io.Writer) *BufferedWriter {
	return &BufferedWriter{
		writer: rawWriter,
		buffer: alloc.NewBuffer().Clear(),
		cached: true,
	}
}

func (this *BufferedWriter) Write(b []byte) (int, error) {
	this.Lock()
	defer this.Unlock()

	if this.writer == nil {
		return 0, io.EOF
	}

	if !this.cached {
		return this.writer.Write(b)
	}
	nBytes, _ := this.buffer.Write(b)
	if this.buffer.IsFull() {
		go this.Flush()
	}
	return nBytes, nil
}

func (this *BufferedWriter) Flush() error {
	this.Lock()
	defer this.Unlock()
	if this.writer == nil {
		return io.EOF
	}

	defer this.buffer.Clear()
	for !this.buffer.IsEmpty() {
		nBytes, err := this.writer.Write(this.buffer.Value)
		if err != nil {
			return err
		}
		this.buffer.SliceFrom(nBytes)
	}
	return nil
}

func (this *BufferedWriter) Cached() bool {
	return this.cached
}

func (this *BufferedWriter) SetCached(cached bool) {
	this.cached = cached
	if !cached && !this.buffer.IsEmpty() {
		this.Flush()
	}
}

func (this *BufferedWriter) Release() {
	this.Lock()
	defer this.Unlock()

	this.Flush()
	this.buffer.Release()
	this.buffer = nil
	this.writer = nil
}
<|endoftext|>


<commit_before>package facebook

import (
	"os"
)

// A user profile.
// http://developers.facebook.com/docs/reference/api/user
type User struct {
	// Identification
	ID string
	// First name
	FirstName string
	// Last name
	LastName string
	// Full name
	Name string
	// A link to the profile
	Link string
	// The Blurb that appears under the profile picture
	About string
	// Birthday
	Birthday string
	// Work history list
	Work []Workplace
	// Education history list
	Educations []Education
	// The contact email adress
	Email string
	// Link to the personal website
	Website string
	// Hometown
	Hometown Object
	// Current location
	Location Object
	// Biography
	Bio string
	// Favorite quotes
	Quotes string
	// Gender
	Gender string
	// Genders the user is interested in
	InterestedIn string
	// Types of relationships the user is seeking for
	MeetingFor string
	// Relationship status
	RelationshipStatus string
	// Religion
	Religion string
	// Political view
	Political string
	// Verification status
	Verified string
	// The user's significant other
	SignificantOther string
	// Timezone
	Timezone string

	// ##### Connections #####
	// TODO: Replace all strings with actual Connection structs
	// The News Feed. Requires read_stream permission
	Home string
	// Wall. Requires read_stream permission to see non-public posts.
	Feed string
	// Photos, videos and posts in which the user has been tagged. Requires read_stream permission.
	Tagged string
	// Own posts. Requires read_stream permission to see non-public posts.
	Posts string
	// Profile picture
	Picture Picture
	// Friends of the user
	Friends string
	// Activities listed on the profile page
	Activities string
	// Interests listed on the profile page
	Interests string
	// Music listed on the profile page
	Music string
	// Books listed on the profile page
	Books string
	// Movies listed on the profile page
	Movies string
	// Television listed on the profile pages
	Television string
	// Pages this user has liked. Requires user_likes or friend_likes permission
	Likes string
	// Photos this user is tagged in. Requires user_photo_video_tags, friend_photo_video_tags and user_photos or friend_photos permissions
	Photos string
	// Photo albums this user has created. Requires user_photos or friend_photos permission
	Albums string
	// Videos this user has been tagged in. Requires user_videos or friend_videos permission
	Videos string
	// Groups this user is a member of. Requires user_groups or friend_groups permission
	Groups string
	// Status updates. Requires read_stream permission
	Statuses string
	// Posted links. Requires read_stream permission
	Links string
	// Notes. Requires read_stream permission
	Notes string
	// Events this user is attending. Requires user_events or friend_events permission
	Events string
	// Threads in this user's inbox. Requires read_mailbox permission
	InBox string
	// Messages in this user's outbox. Requires read_mailbox permission
	OutBox string
	// Updates in this user's inbox. Requires read_mailbox permission
	Updates string
	/* The Facebook pages owned by the current user. If the manage_pages permission has been granted,
	 * this connection also yields access_tokens that can be used to query the Graph API on behalf of the page.
	 */
	Accounts string
	// Places the current user has checked-into.
	Checkins string
	/* The user's outstanding requests for the app associated with the access token.
	 * The access token should be app secret signed and not user session signed. See more info here.
	 */
	PlatformRequests string

	// Not documented in the API but streamed probably Connections
	Locale          string
	UpdatedTime     string
	FanCount        float64
	Mission         string
	Category        string
	Username        string
	Products        string
	Founded         string
	CompanyOverview string
}

func (u *User) String() string {
	return "ID: " + u.ID + "\tName: " + u.Name + "\tFirst name: " + u.FirstName +
		"\tLast name: " + u.LastName + "\tLink: " + u.Link + "\tGender: " +
		u.Gender + "\tLocale: " + u.Locale + "\tUpdated time: " + u.UpdatedTime +
		"\n"
}

func FetchUserIntrospect(name string) (user User, err os.Error) {
	return FetchUser(name + "?metadata=1")
}

func FetchUser(name string) (user User, err os.Error) {
	body, err := fetchBody(name)
	if err != nil {
		return
	}
	data, err := getJsonMap(body)
	if err != nil {
		return
	}
	for key, value := range data {
		switch key {
		case "id":
			user.ID = value.(string)
		case "first_name":
			user.FirstName = value.(string)
		case "last_name":
			user.LastName = value.(string)
		case "name":
			user.Name = value.(string)
		case "link":
			user.Link = value.(string)
		case "about":
			user.About = value.(string)
		case "birthday":
			user.Birthday = value.(string)
		case "work":
			user.Work = parseWork(value.([]interface{}))
		case "education":
			user.Educations = parseEducations(value.([]interface{}))
		case "email":
			user.Email = value.(string)
		case "website":
			user.Website = value.(string)
		case "hometown":
			user.Hometown = parseObject(value.(map[string]interface{}))
		case "location":
			user.Location = parseObject(value.(map[string]interface{}))
		case "bio":
			user.Bio = value.(string)
		case "quotes":
			user.Quotes = value.(string)
		case "gender":
			user.Gender = value.(string)
		case "interested_in":
			user.InterestedIn = value.(string)
		case "meeting_for":
			user.MeetingFor = value.(string)
		case "relationship_status":
			user.RelationshipStatus = value.(string)
		case "religion":
			user.Religion = value.(string)
		case "political":
			user.Political = value.(string)
		case "verified":
			user.Verified = value.(string)
		case "significant_other":
			user.SignificantOther = value.(string)
		case "timezone":
			user.Timezone = value.(string)

		// Connections
		case "picture":
			user.Picture = NewPicture(value.(string))

		// Not documented in the API but streamed
		case "locale":
			user.Locale = value.(string)
		case "mission":
			user.Mission = value.(string)
		case "category":
			user.Category = value.(string)
		case "username":
			user.Username = value.(string)
		case "products":
			user.Products = value.(string)
		case "founded":
			user.Founded = value.(string)
		case "company_overview":
			user.CompanyOverview = value.(string)
		case "fan_count":
			user.FanCount = value.(float64)
		case "type":
			// TODO: Look into type

			// Parse metadata if requested
		case "metadata":
			// TODO: get and parse connections
		default:
			debugInterface(value, key, "Person")
		}
	}
	return
}
<commit_msg>Use Home in User.<commit_after>package facebook

import (
	"os"
)

// A user profile.
// http://developers.facebook.com/docs/reference/api/user
type User struct {
	// Identification
	ID string
	// First name
	FirstName string
	// Last name
	LastName string
	// Full name
	Name string
	// A link to the profile
	Link string
	// The Blurb that appears under the profile picture
	About string
	// Birthday
	Birthday string
	// Work history list
	Work []Workplace
	// Education history list
	Educations []Education
	// The contact email adress
	Email string
	// Link to the personal website
	Website string
	// Hometown
	Hometown Object
	// Current location
	Location Object
	// Biography
	Bio string
	// Favorite quotes
	Quotes string
	// Gender
	Gender string
	// Genders the user is interested in
	InterestedIn string
	// Types of relationships the user is seeking for
	MeetingFor string
	// Relationship status
	RelationshipStatus string
	// Religion
	Religion string
	// Political view
	Political string
	// Verification status
	Verified string
	// The user's significant other
	SignificantOther string
	// Timezone
	Timezone string

	// ##### Connections #####
	// TODO: Replace all strings with actual Connection structs
	// The News Feed. Requires read_stream permission
	Home Home
	// Wall. Requires read_stream permission to see non-public posts.
	Feed string
	// Photos, videos and posts in which the user has been tagged. Requires read_stream permission.
	Tagged string
	// Own posts. Requires read_stream permission to see non-public posts.
	Posts string
	// Profile picture
	Picture Picture
	// Friends of the user
	Friends string
	// Activities listed on the profile page
	Activities string
	// Interests listed on the profile page
	Interests string
	// Music listed on the profile page
	Music string
	// Books listed on the profile page
	Books string
	// Movies listed on the profile page
	Movies string
	// Television listed on the profile pages
	Television string
	// Pages this user has liked. Requires user_likes or friend_likes permission
	Likes string
	// Photos this user is tagged in. Requires user_photo_video_tags, friend_photo_video_tags and user_photos or friend_photos permissions
	Photos string
	// Photo albums this user has created. Requires user_photos or friend_photos permission
	Albums string
	// Videos this user has been tagged in. Requires user_videos or friend_videos permission
	Videos string
	// Groups this user is a member of. Requires user_groups or friend_groups permission
	Groups string
	// Status updates. Requires read_stream permission
	Statuses string
	// Posted links. Requires read_stream permission
	Links string
	// Notes. Requires read_stream permission
	Notes string
	// Events this user is attending. Requires user_events or friend_events permission
	Events string
	// Threads in this user's inbox. Requires read_mailbox permission
	InBox string
	// Messages in this user's outbox. Requires read_mailbox permission
	OutBox string
	// Updates in this user's inbox. Requires read_mailbox permission
	Updates string
	/* The Facebook pages owned by the current user. If the manage_pages permission has been granted,
	 * this connection also yields access_tokens that can be used to query the Graph API on behalf of the page.
	 */
	Accounts string
	// Places the current user has checked-into.
	Checkins string
	/* The user's outstanding requests for the app associated with the access token.
	 * The access token should be app secret signed and not user session signed. See more info here.
	 */
	PlatformRequests string

	// Not documented in the API but streamed
	Locale          string
	UpdatedTime     string
	FanCount        float64
	Mission         string
	Category        string
	Username        string
	Products        string
	Founded         string
	CompanyOverview string
}

func (u *User) String() string {
	return "ID: " + u.ID + "\tName: " + u.Name + "\tFirst name: " + u.FirstName +
		"\tLast name: " + u.LastName + "\tLink: " + u.Link + "\tGender: " +
		u.Gender + "\tLocale: " + u.Locale + "\tUpdated time: " + u.UpdatedTime +
		"\n"
}

func FetchUserIntrospect(name string) (user User, err os.Error) {
	return FetchUser(name + "?metadata=1")
}

func FetchUser(name string) (user User, err os.Error) {
	body, err := fetchBody(name)
	if err != nil {
		return
	}
	data, err := getJsonMap(body)
	if err != nil {
		return
	}
	for key, value := range data {
		switch key {
		case "id":
			user.ID = value.(string)
		case "first_name":
			user.FirstName = value.(string)
		case "last_name":
			user.LastName = value.(string)
		case "name":
			user.Name = value.(string)
		case "link":
			user.Link = value.(string)
		case "about":
			user.About = value.(string)
		case "birthday":
			user.Birthday = value.(string)
		case "work":
			user.Work = parseWork(value.([]interface{}))
		case "education":
			user.Educations = parseEducations(value.([]interface{}))
		case "email":
			user.Email = value.(string)
		case "website":
			user.Website = value.(string)
		case "hometown":
			user.Hometown = parseObject(value.(map[string]interface{}))
		case "location":
			user.Location = parseObject(value.(map[string]interface{}))
		case "bio":
			user.Bio = value.(string)
		case "quotes":
			user.Quotes = value.(string)
		case "gender":
			user.Gender = value.(string)
		case "interested_in":
			user.InterestedIn = value.(string)
		case "meeting_for":
			user.MeetingFor = value.(string)
		case "relationship_status":
			user.RelationshipStatus = value.(string)
		case "religion":
			user.Religion = value.(string)
		case "political":
			user.Political = value.(string)
		case "verified":
			user.Verified = value.(string)
		case "significant_other":
			user.SignificantOther = value.(string)
		case "timezone":
			user.Timezone = value.(string)

		// Connections
		case "picture":
			user.Picture = NewPicture(value.(string))

		// Not documented in the API but streamed
		case "locale":
			user.Locale = value.(string)
		case "mission":
			user.Mission = value.(string)
		case "category":
			user.Category = value.(string)
		case "username":
			user.Username = value.(string)
		case "products":
			user.Products = value.(string)
		case "founded":
			user.Founded = value.(string)
		case "company_overview":
			user.CompanyOverview = value.(string)
		case "fan_count":
			user.FanCount = value.(float64)
		case "type":
			// TODO: Look into type

			// Parse metadata if requested
		case "metadata":
			// TODO: get and parse connections
			metadata := value.(map[string]interface{})
			for k, v := range metadata["connections"].(map[string]interface{}) {
				switch k {
				case "home":
					user.Home, err = FetchHomeByURL(v.(string)) // Pass URL
				}
			}
		default:
			debugInterface(value, key, "Person")
		}
	}
	return
}
<|endoftext|>


<commit_before>package compiler

import (
	"fmt"

	"github.com/twtiger/gosecco/tree"
)

type compilerVisitor struct {
	c        *compiler
	topLevel bool
	jf, jt   label
}

func getLower(k uint64) uint32 {
	return uint32(k)
}

func getUpper(k uint64) uint32 {
	return uint32(k >> 32)
}

func (cv *compilerVisitor) AcceptArgument(a tree.Argument) {
	cv.topLevel = false
	ix := argument[a.Index]
	switch a.Type {
	case tree.Hi:
		cv.c.loadAt(ix.upper)
	case tree.Low:
		cv.c.loadAt(ix.lower)
	default:
		panic(fmt.Sprintf("Incorrect argument type"))
	}
}

func (cv *compilerVisitor) AcceptArithmetic(a tree.Arithmetic) {
	cv.topLevel = false
	a.Left.Accept(cv)
	rightOperand := a.Right.(tree.NumericLiteral)
	cv.c.performArithmetic(a.Op, uint32(rightOperand.Value))
}

func (cv *compilerVisitor) AcceptBinaryNegation(tree.BinaryNegation) {
	cv.topLevel = false
}

func (cv *compilerVisitor) AcceptBooleanLiteral(val tree.BooleanLiteral) {
	if cv.topLevel {
		// TODO: compile here
	} else {
		panic(fmt.Sprintf("Programming error: there should never be any boolean literals left outside of the toplevel if the simplifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
	}
	cv.topLevel = false
}

func (cv *compilerVisitor) AcceptCall(tree.Call) {
	panic(fmt.Sprintf("Programming error: there should never be any unexpanded calls if the unifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
}

func detectSpecialCasesOn(e tree.Expression) (*tree.Argument, *tree.NumericLiteral, bool, bool) {
	switch et := e.(type) {
	case tree.Argument:
		if et.Type == tree.Full {
			return &et, nil, true, false
		}
	case tree.NumericLiteral:
		return nil, &et, false, true
	}
	return nil, nil, false, false
}

func detectSpecialCases(c tree.Comparison) (argL *tree.Argument, argR *tree.Argument, litL *tree.NumericLiteral, litR *tree.NumericLiteral, leftIsArg bool, rightIsArg bool, leftIsLit bool, rightIsLit bool) {
	argL, litL, leftIsArg, leftIsLit = detectSpecialCasesOn(c.Left)
	argR, litR, rightIsArg, rightIsLit = detectSpecialCasesOn(c.Right)
	return
}

func (cv *compilerVisitor) compareExpressionToArg(a *tree.Argument, e tree.Expression, op tree.ComparisonType) {
	e.Accept(cv)
	cv.c.moveAtoX()
	lx := argument[a.Index]
	cv.c.loadAt(lx.upper)

	switch op {
	case tree.NEQL:
		cv.c.jumpOnXComparison(op, cv.jt, noLabel)
	default: // TODO write tests with other comparisons between expressions & args
		cv.c.jumpOnXComparison(op, next, cv.jf)
	}

	cv.c.loadAt(lx.lower)
	cv.c.jumpOnXComparison(op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) AcceptComparison(c tree.Comparison) {
	cv.topLevel = false
	argL, argR, litL, litR, leftArg, rightArg, leftLit, rightLit := detectSpecialCases(c)

	if leftArg && rightLit {
		ix := argument[argL.Index]
		cv.jumpOnK(litR.Value, ix, c.Op)
	}

	if leftLit && rightArg {
		ix := argument[argR.Index]
		cv.jumpOnK(litL.Value, ix, c.Op)
	}

	if leftArg && rightArg {
		rx := argument[argR.Index]
		lx := argument[argL.Index]
		cv.jumpOnX(rx, lx, c.Op)
	}

	if !rightArg && !rightLit && leftArg {
		cv.compareExpressionToArg(argL, c.Right, c.Op)
	}

	if !leftArg && !leftLit && rightArg {
		cv.compareExpressionToArg(argR, c.Left, c.Op)
	}

	if !leftLit && !leftArg && !rightLit && !rightArg {
		c.Left.Accept(cv)
		cv.c.moveAtoX()
		c.Right.Accept(cv)
		cv.c.jumpOnXComparison(c.Op, cv.jt, cv.jf)
	}

}

var count = 0

func nextLabel() label {
	count += 1
	return label(fmt.Sprintf("%d", count))
}

func (cv *compilerVisitor) jumpOnK(l uint64, ix argumentPosition, op tree.ComparisonType) {
	cv.c.loadAt(ix.upper)
	next := nextLabel()

	switch op {
	case tree.NEQL:
		cv.c.jumpOnKComp(getUpper(l), op, cv.jt, noLabel)
	default:
		cv.c.jumpOnKComp(getUpper(l), op, next, cv.jf)
	}
	cv.c.labelHere(next)

	cv.c.loadAt(ix.lower)
	cv.c.jumpOnKComp(getLower(l), op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) jumpOnX(ix argumentPosition, rx argumentPosition, op tree.ComparisonType) {
	cv.c.loadAt(ix.upper)
	cv.c.moveAtoX()
	cv.c.loadAt(rx.upper)
	next := nextLabel()

	switch op {
	case tree.NEQL:
		cv.c.jumpOnXComparison(op, cv.jt, noLabel)
	default: // TODO test cases of other comparisons between two arguments
		cv.c.jumpOnXComparison(op, next, cv.jf)
	}
	cv.c.labelHere(next)

	cv.c.loadAt(ix.lower)
	cv.c.moveAtoX()
	cv.c.loadAt(rx.lower)
	cv.c.jumpOnXComparison(op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) setJumpPoints(p bool) {
	if !p {
		cv.jt = negative
		cv.jf = positive
	} else {
		cv.jt = positive
		cv.jf = negative
	}
}

func (cv *compilerVisitor) goToNextComparison() label {
	n := nextLabel()
	cv.jf = n
	return n
}

func (cv *compilerVisitor) AcceptInclusion(c tree.Inclusion) {
	cv.topLevel = false
	cv.setJumpPoints(c.Positive)

	var n label

	switch et := c.Left.(type) {
	case tree.Argument:
		ix := argument[et.Index]
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}

			switch k := l.(type) {
			case tree.NumericLiteral:
				cv.jumpOnK(k.Value, ix, tree.EQL)
			case tree.Argument:
				rx := argument[k.Index]
				cv.jumpOnX(ix, rx, tree.EQL)
			}
			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}

	case tree.NumericLiteral:
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}

			switch l.(type) {
			case tree.Argument:
				k := l.(tree.Argument)
				ix := argument[k.Index]
				cv.jumpOnK(et.Value, ix, tree.EQL)

			default:
				l.Accept(cv)
				cv.c.jumpOnKComp(getLower(et.Value), tree.EQL, cv.jt, cv.jf)
			}
			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}
	default:
		et.Accept(cv)
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}
			r := l.(tree.NumericLiteral)
			cv.c.jumpOnKComp(getLower(r.Value), tree.EQL, cv.jt, cv.jf)

			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}
	}
}

func (cv *compilerVisitor) AcceptNegation(c tree.Negation) {
	cv.topLevel = false
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: cv.jt, jt: cv.jf}
	c.Operand.Accept(a)
}

func (cv *compilerVisitor) AcceptNumericLiteral(l tree.NumericLiteral) {
}

func (cv *compilerVisitor) AcceptAnd(c tree.And) {
	cv.topLevel = false
	n := nextLabel()
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: cv.jf, jt: n}
	c.Left.Accept(a)
	cv.c.labelHere(n)
	c.Right.Accept(cv)
}

func (cv *compilerVisitor) AcceptOr(c tree.Or) {
	cv.topLevel = false
	n := nextLabel()
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: n, jt: cv.jt}
	c.Left.Accept(a)
	cv.c.labelHere(n)
	c.Right.Accept(cv)
}

func (cv *compilerVisitor) AcceptVariable(tree.Variable) {
	panic(fmt.Sprintf("Programming error: there should never be any unexpanded variables if the unifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
}
<commit_msg>refactor for readability<commit_after>package compiler

import (
	"fmt"

	"github.com/twtiger/gosecco/tree"
)

type compilerVisitor struct {
	c        *compiler
	topLevel bool
	jf, jt   label
}

func getLower(k uint64) uint32 {
	return uint32(k)
}

func getUpper(k uint64) uint32 {
	return uint32(k >> 32)
}

func (cv *compilerVisitor) AcceptArgument(a tree.Argument) {
	cv.topLevel = false
	ix := argument[a.Index]
	switch a.Type {
	case tree.Hi:
		cv.c.loadAt(ix.upper)
	case tree.Low:
		cv.c.loadAt(ix.lower)
	default:
		panic(fmt.Sprintf("Incorrect argument type"))
	}
}

func (cv *compilerVisitor) AcceptArithmetic(a tree.Arithmetic) {
	cv.topLevel = false
	a.Left.Accept(cv)
	rightOperand := a.Right.(tree.NumericLiteral)
	cv.c.performArithmetic(a.Op, uint32(rightOperand.Value))
}

func (cv *compilerVisitor) AcceptBinaryNegation(tree.BinaryNegation) {
	cv.topLevel = false
}

func (cv *compilerVisitor) AcceptBooleanLiteral(val tree.BooleanLiteral) {
	if cv.topLevel {
		// TODO: compile here
	} else {
		panic(fmt.Sprintf("Programming error: there should never be any boolean literals left outside of the toplevel if the simplifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
	}
	cv.topLevel = false
}

func (cv *compilerVisitor) AcceptCall(tree.Call) {
	panic(fmt.Sprintf("Programming error: there should never be any unexpanded calls if the unifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
}

func detectSpecialCasesOn(e tree.Expression) (*tree.Argument, *tree.NumericLiteral, bool, bool) {
	switch et := e.(type) {
	case tree.Argument:
		if et.Type == tree.Full {
			return &et, nil, true, false
		}
	case tree.NumericLiteral:
		return nil, &et, false, true
	}
	return nil, nil, false, false
}

func detectSpecialCases(c tree.Comparison) (argL *tree.Argument, argR *tree.Argument, litL *tree.NumericLiteral, litR *tree.NumericLiteral, leftIsArg bool, rightIsArg bool, leftIsLit bool, rightIsLit bool) {
	argL, litL, leftIsArg, leftIsLit = detectSpecialCasesOn(c.Left)
	argR, litR, rightIsArg, rightIsLit = detectSpecialCasesOn(c.Right)
	return
}

func (cv *compilerVisitor) compareExpressionToArg(a *tree.Argument, e tree.Expression, op tree.ComparisonType) {
	e.Accept(cv)
	cv.c.moveAtoX()
	lx := argument[a.Index]
	cv.c.loadAt(lx.upper)

	switch op {
	case tree.NEQL:
		cv.c.jumpOnXComparison(op, cv.jt, noLabel)
	default: // TODO write tests with other comparisons between expressions & args
		cv.c.jumpOnXComparison(op, next, cv.jf)
	}

	cv.c.loadAt(lx.lower)
	cv.c.jumpOnXComparison(op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) AcceptComparison(c tree.Comparison) {
	cv.topLevel = false
	argL, argR, litL, litR, leftArg, rightArg, leftLit, rightLit := detectSpecialCases(c)

	if leftArg && rightLit {
		ix := argument[argL.Index]
		cv.jumpOnK(litR.Value, ix, c.Op)
	}

	if leftLit && rightArg {
		ix := argument[argR.Index]
		cv.jumpOnK(litL.Value, ix, c.Op)
	}

	if leftArg && rightArg {
		rx := argument[argR.Index]
		lx := argument[argL.Index]
		cv.jumpOnX(rx, lx, c.Op)
	}

	if !rightArg && !rightLit && leftArg {
		cv.compareExpressionToArg(argL, c.Right, c.Op)
	}

	if !leftArg && !leftLit && rightArg {
		cv.compareExpressionToArg(argR, c.Left, c.Op)
	}

	if !leftLit && !leftArg && !rightLit && !rightArg {
		c.Left.Accept(cv)
		cv.c.moveAtoX()
		c.Right.Accept(cv)
		cv.c.jumpOnXComparison(c.Op, cv.jt, cv.jf)
	}

}

var count = 0

func nextLabel() label {
	count += 1
	return label(fmt.Sprintf("%d", count))
}

func (cv *compilerVisitor) jumpOnK(l uint64, ix argumentPosition, op tree.ComparisonType) {
	cv.c.loadAt(ix.upper)
	next := nextLabel()

	switch op {
	case tree.NEQL:
		cv.c.jumpOnKComp(getUpper(l), op, cv.jt, noLabel)
	default:
		cv.c.jumpOnKComp(getUpper(l), op, next, cv.jf)
	}
	cv.c.labelHere(next)

	cv.c.loadAt(ix.lower)
	cv.c.jumpOnKComp(getLower(l), op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) jumpOnX(ix argumentPosition, rx argumentPosition, op tree.ComparisonType) {
	cv.c.loadAt(ix.upper)
	cv.c.moveAtoX()
	cv.c.loadAt(rx.upper)
	next := nextLabel()

	switch op {
	case tree.NEQL:
		cv.c.jumpOnXComparison(op, cv.jt, noLabel)
	default: // TODO test cases of other comparisons between two arguments
		cv.c.jumpOnXComparison(op, next, cv.jf)
	}
	cv.c.labelHere(next)

	cv.c.loadAt(ix.lower)
	cv.c.moveAtoX()
	cv.c.loadAt(rx.lower)
	cv.c.jumpOnXComparison(op, cv.jt, cv.jf)
}

func (cv *compilerVisitor) setJumpPoints(p bool) {
	if !p {
		cv.jt = negative
		cv.jf = positive
	} else {
		cv.jt = positive
		cv.jf = negative
	}
}

func (cv *compilerVisitor) goToNextComparison() label {
	n := nextLabel()
	cv.jf = n
	return n
}

func (cv *compilerVisitor) AcceptInclusion(c tree.Inclusion) {
	cv.topLevel = false
	cv.setJumpPoints(c.Positive)

	var n label
	argL, litL, isArg, isLit := detectSpecialCasesOn(c.Left)

	if isArg {
		ix := argument[argL.Index]
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}

			switch k := l.(type) {
			case tree.NumericLiteral:
				cv.jumpOnK(k.Value, ix, tree.EQL)
			case tree.Argument:
				rx := argument[k.Index]
				cv.jumpOnX(ix, rx, tree.EQL)
			}
			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}

	} else if isLit {
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}

			switch k := l.(type) {
			case tree.Argument:
				ix := argument[k.Index]
				cv.jumpOnK(litL.Value, ix, tree.EQL)
			default:
				l.Accept(cv)
				cv.c.jumpOnKComp(getLower(litL.Value), tree.EQL, cv.jt, cv.jf)
			}
			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}
	} else {
		c.Left.Accept(cv)
		for i, l := range c.Rights {

			if i != len(c.Rights)-1 {
				n = cv.goToNextComparison()
			}
			r := l.(tree.NumericLiteral)
			cv.c.jumpOnKComp(getLower(r.Value), tree.EQL, cv.jt, cv.jf)

			cv.setJumpPoints(c.Positive)
			cv.c.labelHere(n)
		}
	}
}

func (cv *compilerVisitor) AcceptNegation(c tree.Negation) {
	cv.topLevel = false
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: cv.jt, jt: cv.jf}
	c.Operand.Accept(a)
}

func (cv *compilerVisitor) AcceptNumericLiteral(l tree.NumericLiteral) {
}

func (cv *compilerVisitor) AcceptAnd(c tree.And) {
	cv.topLevel = false
	n := nextLabel()
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: cv.jf, jt: n}
	c.Left.Accept(a)
	cv.c.labelHere(n)
	c.Right.Accept(cv)
}

func (cv *compilerVisitor) AcceptOr(c tree.Or) {
	cv.topLevel = false
	n := nextLabel()
	a := &compilerVisitor{c: cv.c, topLevel: false, jf: n, jt: cv.jt}
	c.Left.Accept(a)
	cv.c.labelHere(n)
	c.Right.Accept(cv)
}

func (cv *compilerVisitor) AcceptVariable(tree.Variable) {
	panic(fmt.Sprintf("Programming error: there should never be any unexpanded variables if the unifier works correctly: syscall: %s - %s", cv.c.currentlyCompilingSyscall, tree.ExpressionString(cv.c.currentlyCompilingExpression)))
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"strings"
)

var airlineCodes AirlineCodes

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func init() {
	tableName := "airline"
	tableFields := []string{"Id", "Name", "IATA", "ICAO", "CallSign", "Country", "Comments"}

	CreateTable("127.0.0.1", "picasso", "picasso", "picasso", tableName)

	dat, err := ioutil.ReadFile("airline_codes.csv")
	check(err)

	lines := strings.Split(string(dat), "\n")

	for _, line := range lines {
		if strings.Contains(line, ",") {
			tokens := strings.Split(line, ",")

			if len(tokens[3]) == 0 {
				continue
			}

			AddRow(tableName, tableFields, append(tokens[:2], tokens[3:]...))
		}
	}
}
<commit_msg>Put the mysql address in etcd<commit_after>package main

import (
	"io/ioutil"
	"strings"
)

var airlineCodes AirlineCodes

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func init() {
	tableName := "airline"
	tableFields := []string{"Id", "Name", "IATA", "ICAO", "CallSign", "Country", "Comments"}

	mysql := GetServiceURI("mysql")
	CreateTable(mysql, "picasso", "picasso", "picasso", tableName)

	dat, err := ioutil.ReadFile("airline_codes.csv")
	check(err)

	lines := strings.Split(string(dat), "\n")

	for _, line := range lines {
		if strings.Contains(line, ",") {
			tokens := strings.Split(line, ",")

			if len(tokens[3]) == 0 {
				continue
			}

			AddRow(tableName, tableFields, append(tokens[:2], tokens[3:]...))
		}
	}
}
<|endoftext|>


<commit_before>// Package apex provides Lambda support for Go via a
// Node.js shim and this package for operating over
// stdio.
package apex

import (
	"encoding/json"
	"io"
	"log"
	"os"
)

// Handler handles Lambda events.
type Handler interface {
	Handle(json.RawMessage, *Context) (interface{}, error)
}

// HandlerFunc implements Handler.
type HandlerFunc func(json.RawMessage, *Context) (interface{}, error)

// Handle Lambda event.
func (h HandlerFunc) Handle(event json.RawMessage, ctx *Context) (interface{}, error) {
	return h(event, ctx)
}

// Context represents the context data provided by a Lambda invocation.
type Context struct {
	InvokeID                 string          `json:"invokeid"`
	RequestID                string          `json:"awsRequestId"`
	FunctionName             string          `json:"functionName"`
	FunctionVersion          string          `json:"functionVersion"`
	LogGroupName             string          `json:"logGroupName"`
	LogStreamName            string          `json:"logStreamName"`
	MemoryLimitInMB          string          `json:"memoryLimitInMB"`
	IsDefaultFunctionVersion bool            `json:"isDefaultFunctionVersion"`
	ClientContext            json.RawMessage `json:"clientContext"`
	Identity                 Identity        `json:"identity,omitempty"`
	InvokedFunctionARN       string          `json:"invokedFunctionArn"`
}

// Identity as defined in: http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/lambda.html#identity-context
type Identity struct {
	CognitoIdentityID       string `json:"cognitoIdentityId"`
	CognitoIdentityIDPoolID string `json:"cognitoIdentityPoolId"`
}

// Handle Lambda events with the given handler.
func Handle(h Handler) {
	m := &manager{
		Reader:  os.Stdin,
		Writer:  os.Stdout,
		Handler: h,
	}

	m.Start()
}

// HandleFunc handles Lambda events with the given handler function.
func HandleFunc(h HandlerFunc) {
	Handle(h)
}

// input from the node shim.
type input struct {
	// ID is an itentifier that is boomeranged back to the called,
	// to allow for concurrent commands
	ID      string          `json:"id,omitempty"`
	Event   json.RawMessage `json:"event"`
	Context *Context        `json:"context"`
}

// output for the node shim.
type output struct {
	// The boomeranged ID from the caller
	ID    string      `json:"id,omitempty"`
	Error string      `json:"error,omitempty"`
	Value interface{} `json:"value,omitempty"`
}

// manager for operating over stdio.
type manager struct {
	Reader  io.Reader
	Writer  io.Writer
	Handler Handler
}

// Start the manager.
func (m *manager) Start() {
	dec := json.NewDecoder(m.Reader)
	enc := json.NewEncoder(m.Writer)

	for {
		var msg input
		err := dec.Decode(&msg)

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Printf("error decoding input: %s", err)
			break
		}

		v, err := m.Handler.Handle(msg.Event, msg.Context)
		out := output{ID: msg.ID, Value: v}

		if err != nil {
			out.Error = err.Error()
		}

		if err := enc.Encode(out); err != nil {
			log.Printf("error encoding output: %s", err)
		}
	}
}
<commit_msg>fixed typo in docs<commit_after>// Package apex provides Lambda support for Go via a
// Node.js shim and this package for operating over
// stdio.
package apex

import (
	"encoding/json"
	"io"
	"log"
	"os"
)

// Handler handles Lambda events.
type Handler interface {
	Handle(json.RawMessage, *Context) (interface{}, error)
}

// HandlerFunc implements Handler.
type HandlerFunc func(json.RawMessage, *Context) (interface{}, error)

// Handle Lambda event.
func (h HandlerFunc) Handle(event json.RawMessage, ctx *Context) (interface{}, error) {
	return h(event, ctx)
}

// Context represents the context data provided by a Lambda invocation.
type Context struct {
	InvokeID                 string          `json:"invokeid"`
	RequestID                string          `json:"awsRequestId"`
	FunctionName             string          `json:"functionName"`
	FunctionVersion          string          `json:"functionVersion"`
	LogGroupName             string          `json:"logGroupName"`
	LogStreamName            string          `json:"logStreamName"`
	MemoryLimitInMB          string          `json:"memoryLimitInMB"`
	IsDefaultFunctionVersion bool            `json:"isDefaultFunctionVersion"`
	ClientContext            json.RawMessage `json:"clientContext"`
	Identity                 Identity        `json:"identity,omitempty"`
	InvokedFunctionARN       string          `json:"invokedFunctionArn"`
}

// Identity as defined in: http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/lambda.html#identity-context
type Identity struct {
	CognitoIdentityID       string `json:"cognitoIdentityId"`
	CognitoIdentityIDPoolID string `json:"cognitoIdentityPoolId"`
}

// Handle Lambda events with the given handler.
func Handle(h Handler) {
	m := &manager{
		Reader:  os.Stdin,
		Writer:  os.Stdout,
		Handler: h,
	}

	m.Start()
}

// HandleFunc handles Lambda events with the given handler function.
func HandleFunc(h HandlerFunc) {
	Handle(h)
}

// input from the node shim.
type input struct {
	// ID is an identifier that is boomeranged back to the called,
	// to allow for concurrent commands
	ID      string          `json:"id,omitempty"`
	Event   json.RawMessage `json:"event"`
	Context *Context        `json:"context"`
}

// output for the node shim.
type output struct {
	// The boomeranged ID from the caller
	ID    string      `json:"id,omitempty"`
	Error string      `json:"error,omitempty"`
	Value interface{} `json:"value,omitempty"`
}

// manager for operating over stdio.
type manager struct {
	Reader  io.Reader
	Writer  io.Writer
	Handler Handler
}

// Start the manager.
func (m *manager) Start() {
	dec := json.NewDecoder(m.Reader)
	enc := json.NewEncoder(m.Writer)

	for {
		var msg input
		err := dec.Decode(&msg)

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Printf("error decoding input: %s", err)
			break
		}

		v, err := m.Handler.Handle(msg.Event, msg.Context)
		out := output{ID: msg.ID, Value: v}

		if err != nil {
			out.Error = err.Error()
		}

		if err := enc.Encode(out); err != nil {
			log.Printf("error encoding output: %s", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Println(runtime.GOARCH)
}
<commit_msg>arch command removed<commit_after><|endoftext|>


<commit_before>// 14 march 2014

package ui

import (
	"sync"
	"image"
)

// Area represents a blank canvas upon which programs may draw anything and receive arbitrary events from the user.
// An Area has an explicit size, represented in pixels, that may be different from the size shown in its Window; scrollbars are placed automatically should they be needed.
// The coordinate system of an Area always has an origin of (0,0) which maps to the top-left corner; all image.Points and image.Rectangles sent across Area's channels conform to this.
//
// To handle events to the Area, an Area must be paired with an AreaHandler.
// See AreaHandler for details.
//
// Do not use an Area if you intend to read text.
// Due to platform differences regarding text input,
// keyboard events have beem compromised in
// such a way that attempting to read Unicode data
// in platform-native ways is painful.
// [Use TextArea instead, providing a TextAreaHandler.]
//
// To facilitate development and debugging, for the time being, Areas only work on GTK+.
type Area struct {
	lock			sync.Mutex
	created		bool
	sysData		*sysData
	handler		AreaHandler
	initwidth		int
	initheight		int
}

// AreaHandler represents the events that an Area should respond to.
// You are responsible for the thread safety of any members of the actual type that implements ths interface.
// (Having to use this interface does not strike me as being particularly Go-like, but the nature of Paint makes channel-based event handling a non-option; in practice, deadlocks occur.)
type AreaHandler interface {
	// Paint is called when the Area needs to be redrawn.
	// You MUST handle this event, and you MUST return a valid image, otherwise deadlocks and panicking will occur.
	// The image returned must have the same size as rect (but does not have to have the same origin points).
	// Example:
	// 	imgFromFile, _, err := image.Decode(file)
	// 	if err != nil { panic(err) }
	// 	img := image.NewNRGBA(imgFromFile.Rect)
	// 	draw.Draw(img, img.Rect, imgFromFile, image.ZP, draw.Over)
	// 	// ...
	// 	func (h *myAreaHandler) Paint(rect image.Rectangle) *image.NRGBA {
	// 		return img.SubImage(rect).(*image.NRGBA)
	// 	}
	Paint(rect image.Rectangle) *image.NRGBA

	// Mouse is called when the Area receives a mouse event.
	// You are allowed to do nothing in this handler (to ignore mouse events).
	// See MouseEvent for details.
	Mouse(e MouseEvent)

	// Key is called when the Area receives a keyboard event.
	// You are allowed to do nothing except return false in this handler (to ignore mouse events).
	// Do not do nothing but return true; this may have unintended consequences.
	// See KeyEvent for details.
	Key(e KeyEvent) bool
}

// MouseEvent contains all the information for a mous event sent by Area.Mouse.
// Mouse button IDs start at 1, with 1 being the left mouse button, 2 being the middle mouse button, and 3 being the right mouse button.
// (TODO "If additional buttons are supported, they will be returned with 4 being the first additional button (XBUTTON1 on Windows), 5 being the second (XBUTTON2 on Windows), and so on."?) (TODO get the user-facing name for XBUTTON1/2; find out if there's a way to query available button count)
type MouseEvent struct {
	// Pos is the position of the mouse in the Area at the time of the event.
	// TODO rename to Pt or Point?
	Pos			image.Point

	// If the event was generated by a mouse button being pressed, Down contains the ID of that button.
	// Otherwise, Down contains 0.
	Down		uint

	// If the event was generated by a mouse button being released, Up contains the ID of that button.
	// Otherwise, Up contains 0.
	// If both Down and Up are 0, the event represents mouse movement (with optional held buttons; see below).
	// Down and Up shall not both be nonzero.
	Up			uint

	// If Down is nonzero, Count indicates the number of clicks: 1 for single-click, 2 for double-click.
	// If Count == 2, AT LEAST one event with Count == 1 will have been sent prior.
	// (This is a platform-specific issue: some platforms send one, some send two.)
	Count		uint

	// Modifiers is a bit mask indicating the modifier keys being held during the event.
	Modifiers		Modifiers

	// Held is a slice of button IDs that indicate which mouse buttons are being held during the event.
	// Held will not include Down and Up.
	// (TODO "There is no guarantee that Held is sorted."?)
	Held			[]uint
}

// HeldBits returns Held as a bit mask.
// Bit 0 maps to button 1, bit 1 maps to button 2, etc.
func (e MouseEvent) HeldBits() (h uintptr) {
	for _, x := range e.Held {
		h |= uintptr(1) << (x - 1)
	}
	return h
}

// A KeyEvent represents a keypress in an Area.
//
// In a perfect world, KeyEvent would be 100% predictable.
// Despite my best efforts to do this, however, the various
// differences in input handling between each backend
// environment makes this completely impossible (I can
// work with two of the three identically, but not all three).
// Keep this in mind, and remember that Areas are not ideal
// for text. For more details, see areaplan.md and the linked
// tweets at the end of that file. If you know a better solution
// than the one I have chosen, please let me know.
//
// When you are finished processing the incoming event,
// return whether or not you did something in response
// to the given keystroke from your Key() implementation.
// If you send false, you indicate that you did not handle
// the keypress, and that the system should handle it instead.
// (Some systems will stop processing the keyboard event at all
// if you return true unconditionally, which may result in unwanted
// behavior like global task-switching keystrokes not being processed.)
//
// If a key is pressed that is not supported by ASCII, ExtKey,
// or Modifiers, no KeyEvent will be produced, and package
// ui will act as if false was returned.
type KeyEvent struct {
	// ASCII is a byte representing the character pressed.
	// Despite my best efforts, this cannot be trivialized
	// to produce predictable input rules on all OSs, even if
	// I try to handle physical keys instead of equivalent
	// characters. Therefore, what happens when the user
	// inserts a non-ASCII character is undefined (some systems
	// will give package ui the underlying ASCII key and we
	// return it; other systems do not). This is especially important
	// if the given input method uses Modifiers to enter characters.
	// If the parenthesized rule cannot be followed and the user
	// enters a non-ASCII character, it will be ignored (package ui
	// will act as above regarding keys it cannot handle).
	// In general, alphanumeric characters, ',', '.', '+', '-', and the
	// (space) should be available on all keyboards. Other ASCII
	// whitespace keys mentioned below may be available, but
	// mind layout differences.
	// Whether or not alphabetic characters are uppercase or
	// lowercase is undefined, and cannot be determined solely
	// by examining Modifiers for Shift. Correct code should handle
	// both uppercase and lowercase identically.
	// In addition, ASCII will contain
	// - ' ' (space) if the spacebar was pressed
	// - '\t' if Tab was pressed, regardless of Modifiers
	// - '\n' if any Enter/Return key was pressed, regardless of which
	// - '\b' if the typewriter Backspace key was pressed
	// If this value is zero, see ExtKey.
	ASCII	byte

	// If ASCII is zero, ExtKey contains a predeclared identifier
	// naming an extended key. See ExtKey for details.
	// If both ASCII and ExtKey are zero, a Modifier by itself
	// was pressed. ASCII and ExtKey will not both be nonzero.
	ExtKey		ExtKey

	Modifiers		Modifiers

	// If Up is true, the key was released; if not, the key was pressed.
	// There is no guarantee that all pressed keys shall have
	// corresponding release events (for instance, if the user switches
	// programs while holding the key down, then releases the key).
	// Keys that have been held down are reported as multiple
	// key press events.
	Up			bool
}

// ExtKey represents keys that do not have an ASCII representation.
// There is no way to differentiate between left and right ExtKeys.
type ExtKey uintptr
const (
	Escape ExtKey = iota + 1
	Insert
	Delete
	Home
	End
	PageUp
	PageDown
	Up
	Down
	Left
	Right
	F1		// no guarantee is made that Fn == F1+n in the future
	F2
	F3
	F4
	F5
	F6
	F7
	F8
	F9
	F10
	F11
	F12
	_nextkeys		// for sanity check
)

// Modifiers indicates modifier keys being held during an event.
// There is no way to differentiate between left and right modifier keys.
type Modifiers uintptr
const (
	Ctrl Modifiers = 1 << iota		// the canonical Ctrl keys ([TODO] on Mac OS X, Control on others)
	Alt						// the canonical Alt keys ([TODO] on Mac OS X, Meta on Unix systems, Alt on others)
	Shift						// the Shift keys
	// TODO add Super
)

// NewArea creates a new Area with the given size and handler.
// It panics if handler is nil.
func NewArea(width int, height int, handler AreaHandler) *Area {
	if handler == nil {
		panic("handler passed to NewArea() must not be nil")
	}
	return &Area{
		sysData:		mksysdata(c_area),
		handler:		handler,
		initwidth:		width,
		initheight:		height,
	}
}

// SetSize sets the Area's internal drawing size.
// It has no effect on the actual control size.
func (a *Area) SetSize(width int, height int) {
	a.lock.Lock()
	defer a.lock.Unlock()

	if a.created {
		a.sysData.setAreaSize(width, height)
		return
	}
	a.initwidth = width
	a.initheight = height
}

func (a *Area) make(window *sysData) error {
	a.lock.Lock()
	defer a.lock.Unlock()

	a.sysData.handler = a.handler
	err := a.sysData.make("", window)
	if err != nil {
		return err
	}
	a.sysData.setAreaSize(a.initwidth, a.initheight)
	a.created = true
	return nil
}

func (a *Area) setRect(x int, y int, width int, height int, rr *[]resizerequest) {
	*rr = append(*rr, resizerequest{
		sysData:	a.sysData,
		x:		x,
		y:		y,
		width:	width,
		height:	height,
	})
}

func (a *Area) preferredSize() (width int, height int) {
	return a.sysData.preferredSize()
}
<commit_msg>Fixed a slight documentation error in area.go.<commit_after>// 14 march 2014

package ui

import (
	"sync"
	"image"
)

// Area represents a blank canvas upon which programs may draw anything and receive arbitrary events from the user.
// An Area has an explicit size, represented in pixels, that may be different from the size shown in its Window; scrollbars are placed automatically should they be needed.
// The coordinate system of an Area always has an origin of (0,0) which maps to the top-left corner; all image.Points and image.Rectangles sent across Area's channels conform to this.
//
// To handle events to the Area, an Area must be paired with an AreaHandler.
// See AreaHandler for details.
//
// Do not use an Area if you intend to read text.
// Due to platform differences regarding text input,
// keyboard events have beem compromised in
// such a way that attempting to read Unicode data
// in platform-native ways is painful.
// [Use TextArea instead, providing a TextAreaHandler.]
//
// To facilitate development and debugging, for the time being, Areas only work on GTK+.
type Area struct {
	lock			sync.Mutex
	created		bool
	sysData		*sysData
	handler		AreaHandler
	initwidth		int
	initheight		int
}

// AreaHandler represents the events that an Area should respond to.
// You are responsible for the thread safety of any members of the actual type that implements ths interface.
// (Having to use this interface does not strike me as being particularly Go-like, but the nature of Paint makes channel-based event handling a non-option; in practice, deadlocks occur.)
type AreaHandler interface {
	// Paint is called when the Area needs to be redrawn.
	// You MUST handle this event, and you MUST return a valid image, otherwise deadlocks and panicking will occur.
	// The image returned must have the same size as rect (but does not have to have the same origin points).
	// Example:
	// 	imgFromFile, _, err := image.Decode(file)
	// 	if err != nil { panic(err) }
	// 	img := image.NewNRGBA(imgFromFile.Rect)
	// 	draw.Draw(img, img.Rect, imgFromFile, image.ZP, draw.Over)
	// 	// ...
	// 	func (h *myAreaHandler) Paint(rect image.Rectangle) *image.NRGBA {
	// 		return img.SubImage(rect).(*image.NRGBA)
	// 	}
	Paint(rect image.Rectangle) *image.NRGBA

	// Mouse is called when the Area receives a mouse event.
	// You are allowed to do nothing in this handler (to ignore mouse events).
	// See MouseEvent for details.
	Mouse(e MouseEvent)

	// Key is called when the Area receives a keyboard event.
	// You are allowed to do nothing except return false in this handler (to ignore keyboard events).
	// Do not do nothing but return true; this may have unintended consequences.
	// See KeyEvent for details.
	Key(e KeyEvent) bool
}

// MouseEvent contains all the information for a mous event sent by Area.Mouse.
// Mouse button IDs start at 1, with 1 being the left mouse button, 2 being the middle mouse button, and 3 being the right mouse button.
// (TODO "If additional buttons are supported, they will be returned with 4 being the first additional button (XBUTTON1 on Windows), 5 being the second (XBUTTON2 on Windows), and so on."?) (TODO get the user-facing name for XBUTTON1/2; find out if there's a way to query available button count)
type MouseEvent struct {
	// Pos is the position of the mouse in the Area at the time of the event.
	// TODO rename to Pt or Point?
	Pos			image.Point

	// If the event was generated by a mouse button being pressed, Down contains the ID of that button.
	// Otherwise, Down contains 0.
	Down		uint

	// If the event was generated by a mouse button being released, Up contains the ID of that button.
	// Otherwise, Up contains 0.
	// If both Down and Up are 0, the event represents mouse movement (with optional held buttons; see below).
	// Down and Up shall not both be nonzero.
	Up			uint

	// If Down is nonzero, Count indicates the number of clicks: 1 for single-click, 2 for double-click.
	// If Count == 2, AT LEAST one event with Count == 1 will have been sent prior.
	// (This is a platform-specific issue: some platforms send one, some send two.)
	Count		uint

	// Modifiers is a bit mask indicating the modifier keys being held during the event.
	Modifiers		Modifiers

	// Held is a slice of button IDs that indicate which mouse buttons are being held during the event.
	// Held will not include Down and Up.
	// (TODO "There is no guarantee that Held is sorted."?)
	Held			[]uint
}

// HeldBits returns Held as a bit mask.
// Bit 0 maps to button 1, bit 1 maps to button 2, etc.
func (e MouseEvent) HeldBits() (h uintptr) {
	for _, x := range e.Held {
		h |= uintptr(1) << (x - 1)
	}
	return h
}

// A KeyEvent represents a keypress in an Area.
//
// In a perfect world, KeyEvent would be 100% predictable.
// Despite my best efforts to do this, however, the various
// differences in input handling between each backend
// environment makes this completely impossible (I can
// work with two of the three identically, but not all three).
// Keep this in mind, and remember that Areas are not ideal
// for text. For more details, see areaplan.md and the linked
// tweets at the end of that file. If you know a better solution
// than the one I have chosen, please let me know.
//
// When you are finished processing the incoming event,
// return whether or not you did something in response
// to the given keystroke from your Key() implementation.
// If you send false, you indicate that you did not handle
// the keypress, and that the system should handle it instead.
// (Some systems will stop processing the keyboard event at all
// if you return true unconditionally, which may result in unwanted
// behavior like global task-switching keystrokes not being processed.)
//
// If a key is pressed that is not supported by ASCII, ExtKey,
// or Modifiers, no KeyEvent will be produced, and package
// ui will act as if false was returned.
type KeyEvent struct {
	// ASCII is a byte representing the character pressed.
	// Despite my best efforts, this cannot be trivialized
	// to produce predictable input rules on all OSs, even if
	// I try to handle physical keys instead of equivalent
	// characters. Therefore, what happens when the user
	// inserts a non-ASCII character is undefined (some systems
	// will give package ui the underlying ASCII key and we
	// return it; other systems do not). This is especially important
	// if the given input method uses Modifiers to enter characters.
	// If the parenthesized rule cannot be followed and the user
	// enters a non-ASCII character, it will be ignored (package ui
	// will act as above regarding keys it cannot handle).
	// In general, alphanumeric characters, ',', '.', '+', '-', and the
	// (space) should be available on all keyboards. Other ASCII
	// whitespace keys mentioned below may be available, but
	// mind layout differences.
	// Whether or not alphabetic characters are uppercase or
	// lowercase is undefined, and cannot be determined solely
	// by examining Modifiers for Shift. Correct code should handle
	// both uppercase and lowercase identically.
	// In addition, ASCII will contain
	// - ' ' (space) if the spacebar was pressed
	// - '\t' if Tab was pressed, regardless of Modifiers
	// - '\n' if any Enter/Return key was pressed, regardless of which
	// - '\b' if the typewriter Backspace key was pressed
	// If this value is zero, see ExtKey.
	ASCII	byte

	// If ASCII is zero, ExtKey contains a predeclared identifier
	// naming an extended key. See ExtKey for details.
	// If both ASCII and ExtKey are zero, a Modifier by itself
	// was pressed. ASCII and ExtKey will not both be nonzero.
	ExtKey		ExtKey

	Modifiers		Modifiers

	// If Up is true, the key was released; if not, the key was pressed.
	// There is no guarantee that all pressed keys shall have
	// corresponding release events (for instance, if the user switches
	// programs while holding the key down, then releases the key).
	// Keys that have been held down are reported as multiple
	// key press events.
	Up			bool
}

// ExtKey represents keys that do not have an ASCII representation.
// There is no way to differentiate between left and right ExtKeys.
type ExtKey uintptr
const (
	Escape ExtKey = iota + 1
	Insert
	Delete
	Home
	End
	PageUp
	PageDown
	Up
	Down
	Left
	Right
	F1		// no guarantee is made that Fn == F1+n in the future
	F2
	F3
	F4
	F5
	F6
	F7
	F8
	F9
	F10
	F11
	F12
	_nextkeys		// for sanity check
)

// Modifiers indicates modifier keys being held during an event.
// There is no way to differentiate between left and right modifier keys.
type Modifiers uintptr
const (
	Ctrl Modifiers = 1 << iota		// the canonical Ctrl keys ([TODO] on Mac OS X, Control on others)
	Alt						// the canonical Alt keys ([TODO] on Mac OS X, Meta on Unix systems, Alt on others)
	Shift						// the Shift keys
	// TODO add Super
)

// NewArea creates a new Area with the given size and handler.
// It panics if handler is nil.
func NewArea(width int, height int, handler AreaHandler) *Area {
	if handler == nil {
		panic("handler passed to NewArea() must not be nil")
	}
	return &Area{
		sysData:		mksysdata(c_area),
		handler:		handler,
		initwidth:		width,
		initheight:		height,
	}
}

// SetSize sets the Area's internal drawing size.
// It has no effect on the actual control size.
func (a *Area) SetSize(width int, height int) {
	a.lock.Lock()
	defer a.lock.Unlock()

	if a.created {
		a.sysData.setAreaSize(width, height)
		return
	}
	a.initwidth = width
	a.initheight = height
}

func (a *Area) make(window *sysData) error {
	a.lock.Lock()
	defer a.lock.Unlock()

	a.sysData.handler = a.handler
	err := a.sysData.make("", window)
	if err != nil {
		return err
	}
	a.sysData.setAreaSize(a.initwidth, a.initheight)
	a.created = true
	return nil
}

func (a *Area) setRect(x int, y int, width int, height int, rr *[]resizerequest) {
	*rr = append(*rr, resizerequest{
		sysData:	a.sysData,
		x:		x,
		y:		y,
		width:	width,
		height:	height,
	})
}

func (a *Area) preferredSize() (width int, height int) {
	return a.sysData.preferredSize()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/hashicorp/consul-template/test"
)

func TestRun_printsErrors(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -bacon delicious", " ")

	status := cli.Run(args)
	if status == ExitCodeOK {
		t.Fatal("expected not OK exit code")
	}

	expected := "flag provided but not defined: -bacon"
	if !strings.Contains(errStream.String(), expected) {
		t.Errorf("expected %q to eq %q", errStream.String(), expected)
	}
}

func TestRun_versionFlag(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -version", " ")

	status := cli.Run(args)
	if status != ExitCodeOK {
		t.Errorf("expected %q to eq %q", status, ExitCodeOK)
	}

	expected := fmt.Sprintf("consul-template v%s", Version)
	if !strings.Contains(errStream.String(), expected) {
		t.Errorf("expected %q to eq %q", errStream.String(), expected)
	}
}

func TestRun_parseError(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -bacon delicious", " ")

	status := cli.Run(args)
	if status != ExitCodeParseFlagsError {
		t.Errorf("expected %q to eq %q", status, ExitCodeParseFlagsError)
	}

	expected := "flag provided but not defined: -bacon"
	if !strings.Contains(errStream.String(), expected) {
		t.Fatalf("expected %q to contain %q", errStream.String(), expected)
	}
}

func TestRun_waitFlagError(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -wait=watermelon:bacon", " ")

	status := cli.Run(args)
	if status != ExitCodeParseWaitError {
		t.Errorf("expected %q to eq %q", status, ExitCodeParseWaitError)
	}

	expected := "time: invalid duration watermelon"
	if !strings.Contains(errStream.String(), expected) {
		t.Fatalf("expected %q to contain %q", errStream.String(), expected)
	}
}

func TestRun_onceFlag(t *testing.T) {
	template := test.CreateTempfile([]byte(`
	{{range service "consul"}}{{.Name}}{{end}}
  `), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}

	command := fmt.Sprintf("consul-template -consul demo.consul.io -template %s:%s -once", template.Name(), out.Name())
	args := strings.Split(command, " ")

	ch := make(chan int, 1)

	go func() {
		ch <- cli.Run(args)
	}()

	select {
	case status := <-ch:
		if status != ExitCodeOK {
			t.Errorf("expected %d to eq %d", status, ExitCodeOK)
			t.Errorf("stderr: %s", errStream.String())
		}
	case <-time.After(5 * time.Second):
		t.Errorf("expected data, but nothing was returned")
	}
}

func TestQuiescence(t *testing.T) {
	t.Skip("TODO")
}

func TestReload_sighup(t *testing.T) {
	template := test.CreateTempfile([]byte("initial value"), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}

	command := fmt.Sprintf("consul-template -template %s:%s", template.Name(), out.Name())
	args := strings.Split(command, " ")

	go cli.Run(args)
	defer cli.shutdown()

	// Sleep to let the Runner run
	time.Sleep(100 * time.Millisecond)

	newValue := []byte("new value")
	ioutil.WriteFile(template.Name(), newValue, 0644)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)

	// Sleep to give the file time to write
	time.Sleep(100 * time.Millisecond)

	contents, err := ioutil.ReadFile(out.Name())
	if err != nil {
		t.Fatal(err)
	}

	if !bytes.Equal(contents, newValue) {
		t.Errorf("expected %q to contain %q", contents, newValue)
	}
}

func TestBuildConfig_singleFile(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		consul = "127.0.0.1"
	`), t)
	defer test.DeleteTempfile(configFile, t)

	config := new(Config)
	if err := buildConfig(config, configFile.Name()); err != nil {
		t.Fatal(err)
	}

	expected := "127.0.0.1"
	if config.Consul != expected {
		t.Errorf("expected %q to be %q", config.Consul, expected)
	}
}

func TestBuildConfig_NonExistentDirectory(t *testing.T) {
	// Create a directory and then delete it
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.RemoveAll(configDir); err != nil {
		t.Fatal(err)
	}

	config := new(Config)
	err = buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "missing file/folder"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_EmptyDirectory(t *testing.T) {
	// Create a directory with no files
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(configDir)

	config := new(Config)
	err = buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "must contain at least one configuration file"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_BadConfigs(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		totally not a vaild config
	`), t)
	defer test.DeleteTempfile(configFile, t)

	configDir := filepath.Dir(configFile.Name())

	config := new(Config)
	err := buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "1 error(s) occurred"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_configDir(t *testing.T) {
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	configFile1, err := ioutil.TempFile(configDir, "")
	if err != nil {
		t.Fatal(err)
	}
	config1 := []byte(`
		consul = "127.0.0.1:8500"
	`)
	_, err = configFile1.Write(config1)
	if err != nil {
		t.Fatal(err)
	}
	configFile2, err := ioutil.TempFile(configDir, "")
	if err != nil {
		t.Fatal(err)
	}
	config2 := []byte(`
		template {
		  source = "/path/on/disk/to/template"
		  destination = "/path/on/disk/where/template/will/render"
		  command = "optional command to run when the template is updated"
		}
	`)
	_, err = configFile2.Write(config2)
	if err != nil {
		t.Fatal(err)
	}

	config := new(Config)
	if err := buildConfig(config, configDir); err != nil {
		t.Fatal(err)
	}

	expectedConfig := Config{
		Consul: "127.0.0.1:8500",
		ConfigTemplates: []*ConfigTemplate{{
			Source:      "/path/on/disk/to/template",
			Destination: "/path/on/disk/where/template/will/render",
			Command:     "optional command to run when the template is updated",
		}},
	}
	if expectedConfig.Consul != config.Consul {
		t.Fatalf("Config files failed to combine. Expected Consul to be %s but got %s", expectedConfig.Consul, config.Consul)
	}
	if len(config.ConfigTemplates) != len(expectedConfig.ConfigTemplates) {
		t.Fatalf("Expected %d ConfigTemplate but got %d", len(expectedConfig.ConfigTemplates), len(config.ConfigTemplates))
	}
	for i, expectTemplate := range expectedConfig.ConfigTemplates {
		actualTemplate := config.ConfigTemplates[i]
		if actualTemplate.Source != expectTemplate.Source {
			t.Fatalf("Expected template Source to be %s but got %s", expectTemplate.Source, actualTemplate.Source)
		}
		if actualTemplate.Destination != expectTemplate.Destination {
			t.Fatalf("Expected template Destination to be %s but got %s", expectTemplate.Destination, actualTemplate.Destination)
		}
		if actualTemplate.Command != expectTemplate.Command {
			t.Fatalf("Expected template Command to be %s but got %s", expectTemplate.Command, actualTemplate.Command)
		}
	}
}
<commit_msg>Skip the -once test for now<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/hashicorp/consul-template/test"
)

func TestRun_printsErrors(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -bacon delicious", " ")

	status := cli.Run(args)
	if status == ExitCodeOK {
		t.Fatal("expected not OK exit code")
	}

	expected := "flag provided but not defined: -bacon"
	if !strings.Contains(errStream.String(), expected) {
		t.Errorf("expected %q to eq %q", errStream.String(), expected)
	}
}

func TestRun_versionFlag(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -version", " ")

	status := cli.Run(args)
	if status != ExitCodeOK {
		t.Errorf("expected %q to eq %q", status, ExitCodeOK)
	}

	expected := fmt.Sprintf("consul-template v%s", Version)
	if !strings.Contains(errStream.String(), expected) {
		t.Errorf("expected %q to eq %q", errStream.String(), expected)
	}
}

func TestRun_parseError(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -bacon delicious", " ")

	status := cli.Run(args)
	if status != ExitCodeParseFlagsError {
		t.Errorf("expected %q to eq %q", status, ExitCodeParseFlagsError)
	}

	expected := "flag provided but not defined: -bacon"
	if !strings.Contains(errStream.String(), expected) {
		t.Fatalf("expected %q to contain %q", errStream.String(), expected)
	}
}

func TestRun_waitFlagError(t *testing.T) {
	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}
	args := strings.Split("consul-template -wait=watermelon:bacon", " ")

	status := cli.Run(args)
	if status != ExitCodeParseWaitError {
		t.Errorf("expected %q to eq %q", status, ExitCodeParseWaitError)
	}

	expected := "time: invalid duration watermelon"
	if !strings.Contains(errStream.String(), expected) {
		t.Fatalf("expected %q to contain %q", errStream.String(), expected)
	}
}

func TestRun_onceFlag(t *testing.T) {
	t.Skip("Pending a rewrite of the Runner")

	template := test.CreateTempfile([]byte(`
	{{range service "consul"}}{{.Name}}{{end}}
  `), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}

	command := fmt.Sprintf("consul-template -consul demo.consul.io -template %s:%s -once", template.Name(), out.Name())
	args := strings.Split(command, " ")

	ch := make(chan int, 1)
	go func() {
		ch <- cli.Run(args)
	}()

	select {
	case status := <-ch:
		if status != ExitCodeOK {
			t.Errorf("expected %d to eq %d", status, ExitCodeOK)
			t.Errorf("stderr: %s", errStream.String())
		}
	case <-time.After(2 * time.Second):
		t.Errorf("expected exit, did not exit after 2 seconds")
	}
}

func TestQuiescence(t *testing.T) {
	t.Skip("TODO")
}

func TestReload_sighup(t *testing.T) {
	template := test.CreateTempfile([]byte("initial value"), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
	cli := &CLI{outStream: outStream, errStream: errStream}

	command := fmt.Sprintf("consul-template -template %s:%s", template.Name(), out.Name())
	args := strings.Split(command, " ")

	go cli.Run(args)
	defer cli.shutdown()

	// Sleep to let the Runner run
	time.Sleep(100 * time.Millisecond)

	newValue := []byte("new value")
	ioutil.WriteFile(template.Name(), newValue, 0644)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)

	// Sleep to give the file time to write
	time.Sleep(100 * time.Millisecond)

	contents, err := ioutil.ReadFile(out.Name())
	if err != nil {
		t.Fatal(err)
	}

	if !bytes.Equal(contents, newValue) {
		t.Errorf("expected %q to contain %q", contents, newValue)
	}
}

func TestBuildConfig_singleFile(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		consul = "127.0.0.1"
	`), t)
	defer test.DeleteTempfile(configFile, t)

	config := new(Config)
	if err := buildConfig(config, configFile.Name()); err != nil {
		t.Fatal(err)
	}

	expected := "127.0.0.1"
	if config.Consul != expected {
		t.Errorf("expected %q to be %q", config.Consul, expected)
	}
}

func TestBuildConfig_NonExistentDirectory(t *testing.T) {
	// Create a directory and then delete it
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.RemoveAll(configDir); err != nil {
		t.Fatal(err)
	}

	config := new(Config)
	err = buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "missing file/folder"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_EmptyDirectory(t *testing.T) {
	// Create a directory with no files
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(configDir)

	config := new(Config)
	err = buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "must contain at least one configuration file"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_BadConfigs(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		totally not a vaild config
	`), t)
	defer test.DeleteTempfile(configFile, t)

	configDir := filepath.Dir(configFile.Name())

	config := new(Config)
	err := buildConfig(config, configDir)
	if err == nil {
		t.Fatalf("expected error, but nothing was returned")
	}

	expected := "1 error(s) occurred"
	if !strings.Contains(err.Error(), expected) {
		t.Fatalf("expected %q to contain %q", err.Error(), expected)
	}
}

func TestBuildConfig_configDir(t *testing.T) {
	configDir, err := ioutil.TempDir(os.TempDir(), "")
	if err != nil {
		t.Fatal(err)
	}
	configFile1, err := ioutil.TempFile(configDir, "")
	if err != nil {
		t.Fatal(err)
	}
	config1 := []byte(`
		consul = "127.0.0.1:8500"
	`)
	_, err = configFile1.Write(config1)
	if err != nil {
		t.Fatal(err)
	}
	configFile2, err := ioutil.TempFile(configDir, "")
	if err != nil {
		t.Fatal(err)
	}
	config2 := []byte(`
		template {
		  source = "/path/on/disk/to/template"
		  destination = "/path/on/disk/where/template/will/render"
		  command = "optional command to run when the template is updated"
		}
	`)
	_, err = configFile2.Write(config2)
	if err != nil {
		t.Fatal(err)
	}

	config := new(Config)
	if err := buildConfig(config, configDir); err != nil {
		t.Fatal(err)
	}

	expectedConfig := Config{
		Consul: "127.0.0.1:8500",
		ConfigTemplates: []*ConfigTemplate{{
			Source:      "/path/on/disk/to/template",
			Destination: "/path/on/disk/where/template/will/render",
			Command:     "optional command to run when the template is updated",
		}},
	}
	if expectedConfig.Consul != config.Consul {
		t.Fatalf("Config files failed to combine. Expected Consul to be %s but got %s", expectedConfig.Consul, config.Consul)
	}
	if len(config.ConfigTemplates) != len(expectedConfig.ConfigTemplates) {
		t.Fatalf("Expected %d ConfigTemplate but got %d", len(expectedConfig.ConfigTemplates), len(config.ConfigTemplates))
	}
	for i, expectTemplate := range expectedConfig.ConfigTemplates {
		actualTemplate := config.ConfigTemplates[i]
		if actualTemplate.Source != expectTemplate.Source {
			t.Fatalf("Expected template Source to be %s but got %s", expectTemplate.Source, actualTemplate.Source)
		}
		if actualTemplate.Destination != expectTemplate.Destination {
			t.Fatalf("Expected template Destination to be %s but got %s", expectTemplate.Destination, actualTemplate.Destination)
		}
		if actualTemplate.Command != expectTemplate.Command {
			t.Fatalf("Expected template Command to be %s but got %s", expectTemplate.Command, actualTemplate.Command)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/fadion/aria/interpreter"
	"github.com/fadion/aria/lexer"
	"github.com/fadion/aria/parser"
	"github.com/fadion/aria/reader"
	"github.com/fadion/aria/reporter"
	"github.com/fatih/color"
	"github.com/urfave/cli"
	"io/ioutil"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "aria"
	app.Usage = "an expressive, noiseless, interpreted toy language"
	app.Authors = []cli.Author{{
		Name:  "Fadion Dashi",
		Email: "jonidashi@gmail.com",
	}}
	app.Version = "0.1.0"

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "Run an Aria source file",
			Action: func(c *cli.Context) error {
				if len(c.Args()) != 1 {
					color.Red("Run expects a source file as argument.")
				}

				file := c.Args()[0]
				source, err := ioutil.ReadFile(file)
				if err != nil {
					color.Red("Couldn't read '%s'", file)
					return nil
				}

				lex := lexer.New(reader.New(source))
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				parse := parser.New(lex)
				program := parse.Parse()
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				runner := interpreter.New()
				runner.Interpret(program, interpreter.NewScope())
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				return nil
			},
		},
		{
			Name:  "repl",
			Usage: "Start the interactive repl",
			Action: func(c *cli.Context) error {
				input := bufio.NewReader(os.Stdin)
				color.Yellow(`    _   ___ ___   _
   /_\ | _ \_ _| /_\
  / _ \|   /| | / _ \
 /_/ \_\_|_\___/_/ \_\
 `)
				color.White("Close by pressing CTRL+C")
				fmt.Println()

				scope := interpreter.NewScope()

				for {
					color.Set(color.FgWhite)
					fmt.Print(">> ")
					color.Unset()

					source, _ := input.ReadBytes('\n')
					lex := lexer.New(reader.New(source))
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					parse := parser.New(lex)
					program := parse.Parse()
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					runner := interpreter.New()
					object := runner.Interpret(program, scope)
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					if object != nil {
						fmt.Println(object.Inspect())
					}
				}

				return nil
			},
		},
	}

	app.CommandNotFound = func(ctx *cli.Context, command string) {
		fmt.Fprintf(ctx.App.Writer, "Command %q doesn't exist.\n", command)
	}

	app.Run(os.Args)
}

func printErrors() {
	color.White("Oops, found some errors:")
	for _, v := range reporter.GetErrors() {
		color.Red(v)
	}
	reporter.ClearErrors()
}
<commit_msg>Remove unreachable return<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/fadion/aria/interpreter"
	"github.com/fadion/aria/lexer"
	"github.com/fadion/aria/parser"
	"github.com/fadion/aria/reader"
	"github.com/fadion/aria/reporter"
	"github.com/fatih/color"
	"github.com/urfave/cli"
	"io/ioutil"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "aria"
	app.Usage = "an expressive, noiseless, interpreted toy language"
	app.Authors = []cli.Author{{
		Name:  "Fadion Dashi",
		Email: "jonidashi@gmail.com",
	}}
	app.Version = "0.1.0"

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "Run an Aria source file",
			Action: func(c *cli.Context) error {
				if len(c.Args()) != 1 {
					color.Red("Run expects a source file as argument.")
				}

				file := c.Args()[0]
				source, err := ioutil.ReadFile(file)
				if err != nil {
					color.Red("Couldn't read '%s'", file)
					return nil
				}

				lex := lexer.New(reader.New(source))
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				parse := parser.New(lex)
				program := parse.Parse()
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				runner := interpreter.New()
				runner.Interpret(program, interpreter.NewScope())
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				return nil
			},
		},
		{
			Name:  "repl",
			Usage: "Start the interactive repl",
			Action: func(c *cli.Context) error {
				input := bufio.NewReader(os.Stdin)
				color.Yellow(`    _   ___ ___   _
   /_\ | _ \_ _| /_\
  / _ \|   /| | / _ \
 /_/ \_\_|_\___/_/ \_\
 `)
				color.White("Close by pressing CTRL+C")
				fmt.Println()

				scope := interpreter.NewScope()

				for {
					color.Set(color.FgWhite)
					fmt.Print(">> ")
					color.Unset()

					source, _ := input.ReadBytes('\n')
					lex := lexer.New(reader.New(source))
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					parse := parser.New(lex)
					program := parse.Parse()
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					runner := interpreter.New()
					object := runner.Interpret(program, scope)
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					if object != nil {
						fmt.Println(object.Inspect())
					}
				}
			},
		},
	}

	app.CommandNotFound = func(ctx *cli.Context, command string) {
		fmt.Fprintf(ctx.App.Writer, "Command %q doesn't exist.\n", command)
	}

	app.Run(os.Args)
}

func printErrors() {
	color.White("Oops, found some errors:")
	for _, v := range reporter.GetErrors() {
		color.Red(v)
	}
	reporter.ClearErrors()
}
<|endoftext|>