From 38406779c3ac37bc285cf6355b9a395237479276 Mon Sep 17 00:00:00 2001 From: kscarlett Date: Mon, 23 Jul 2018 23:41:08 +0100 Subject: [PATCH 1/5] ci(travis): Disable automatic deployment temporarily Automatic deployment to GitHub Releases was acting up, so it will temporarily be done manually until I find the time to tinker around with automated deployment again. --- .travis.yml | 11 ++++++----- deploy.sh | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdea514..7a6401d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,8 +21,9 @@ before_install: script: - $GOPATH/bin/goveralls -service=travis-ci -deploy: - provider: script - script: bash deploy.sh - on: - branch: master +# NOTE: temporarily disabled automatic uploading of releases - the releases are supposed to be stable, so manual deploys are doable, and the automated pipeline is only causing issues +#deploy: +# provider: script +# script: bash deploy.sh +# on: +# branch: master diff --git a/deploy.sh b/deploy.sh index d72c0aa..ab2a628 100644 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ export GIT_COMMIT=$(git rev-list -1 HEAD) export GIT_TAG=$(git describe --tags) gox -osarch="windows/amd64 darwin/amd64 linux/amd64 linux/arm" -output "dist/hussar_{{.OS}}-{{.Arch}}" -ldflags "-X main.GitCommit=$GIT_COMMIT" -ldflags "-X main.VersionString=$GIT_TAG" -ghr --username hussar-lang --token $GITHUB_TOKEN --replace --prerelease --debug pre-release dist/ \ No newline at end of file +#ghr --username hussar-lang --token $GITHUB_TOKEN --replace --prerelease --debug pre-release dist/ \ No newline at end of file From 25f840fed2b8366e529ac158c0431aa1ea1ef098 Mon Sep 17 00:00:00 2001 From: kscarlett Date: Thu, 30 Aug 2018 14:44:45 +0100 Subject: [PATCH 2/5] feat(tools): Improve main tools Improve main tools to improve future ability to add more tools to core #1 --- cmd/env.go | 26 +++++++++ cmd/interactive.go | 19 +++++++ cmd/root.go | 138 +++++++++++++++++++++++++++++++++++++++++++++ cmd/run.go | 109 +++++++++++++++++++++++++++++++++++ main.go | 87 +--------------------------- 5 files changed, 295 insertions(+), 84 deletions(-) create mode 100644 cmd/env.go create mode 100644 cmd/interactive.go create mode 100644 cmd/root.go create mode 100644 cmd/run.go diff --git a/cmd/env.go b/cmd/env.go new file mode 100644 index 0000000..8674731 --- /dev/null +++ b/cmd/env.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "fmt" + "os" + "runtime" + + "github.com/spf13/cobra" +) + +var env = &cobra.Command{ + Use: "env", + Short: "Displays the current environment setup used by Hussar", + Run: func(cmd *cobra.Command, args []string) { + printEnvironment() + }, +} + +func printEnvironment() { + fmt.Printf("arch: %s", runtime.GOARCH) + fmt.Printf("os: %s", runtime.GOOS) + fmt.Printf("bin: %s", os.Args[0]) + fmt.Printf("gc: %s", runtime.Version()) + fmt.Printf("vers: %s", version) + fmt.Printf("build: %s", build) +} diff --git a/cmd/interactive.go b/cmd/interactive.go new file mode 100644 index 0000000..d219d0c --- /dev/null +++ b/cmd/interactive.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/hussar-lang/hussar/repl" + + "github.com/spf13/cobra" +) + +var interactive = &cobra.Command{ + Use: "interactive", + Short: "Start the interactive shell", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Starting Hussar interactive interpreter.") + repl.Start(os.Stdin, os.Stdout) + }, +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..424ef90 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,138 @@ +package cmd + +import ( + "fmt" + + log "github.com/sirupsen/logrus" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + version string + build string +) + +var rootCmd = &cobra.Command{ + Use: "hussar", +} + +// Setup populates the version and build fields +func Setup(versionStr string, buildStr string) { + version = versionStr + build = buildStr + rootCmd.Short = fmt.Sprintf("The Hussar programming language - %s (build %s)", version, build) + rootCmd.SetVersionTemplate(fmt.Sprintf("%s (build %s)", version, build)) +} + +// Execute executes the commands +func Execute() { + rootCmd.AddCommand(run, interactive, env) + if err := rootCmd.Execute(); err != nil { + log.WithError(err).Fatal() + } +} + +func init() { + cobra.OnInitialize(initialize) + + // Global flags + rootCmd.PersistentFlags().String("log.level", "warn", "one of debug, info, warn, error or fatal") + rootCmd.PersistentFlags().String("log.format", "text", "one of text or json") + + // Flag binding + viper.BindPFlags(rootCmd.PersistentFlags()) +} + +func initialize() { + // Environment variables + viper.SetEnvPrefix("hussar") + viper.AutomaticEnv() + + // Configuration file + viper.SetConfigName("hs-config") + viper.AddConfigPath(".") + viper.AddConfigPath("$HOME/.hussar/") + if err := viper.ReadInConfig(); err != nil { + log.Info("No valid configuration file found") + } + lvl := viper.GetString("log.level") + l, err := log.ParseLevel(lvl) + if err != nil { + log.WithField("level", lvl).Warn("Invalid log level, fallback to 'warn'") + } else { + log.SetLevel(l) + } + switch viper.GetString("log.format") { + case "json": + log.SetFormatter(&log.JSONFormatter{}) + default: + case "text": + log.SetFormatter(&log.TextFormatter{}) + } +} + +/*import ( + "fmt" + "io" + "io/ioutil" + "os" + + "github.com/hussar-lang/hussar/evaluator" + "github.com/hussar-lang/hussar/lexer" + "github.com/hussar-lang/hussar/object" + "github.com/hussar-lang/hussar/parser" + "github.com/hussar-lang/hussar/repl" + + log "github.com/sirupsen/logrus" + "github.com/ttacon/chalk" + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + GitCommit string + VersionString string + + app = kingpin.New("hussar", "The Hussar interpreter") + verbose = app.Flag("verbose", "Enable verbose logging.").Short('v').Bool() + + // TODO: run interactive mode if no subcommand was given (see #1) + interactive = app.Command("interactive", "Interactive REPL") + + run = app.Command("run", "Run Hussar code") + runFile = run.Flag("file", "Code to run").Required().Short('f').ExistingFile() +) + +func init() { + log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) + log.SetOutput(os.Stdout) +} + +func main() { + app.Version(fmt.Sprintf("%s (%s)", VersionString, GitCommit)) + args, err := app.Parse(os.Args[1:]) + + if *verbose { + log.SetLevel(log.DebugLevel) + } else { + log.SetLevel(log.WarnLevel) + } + + switch kingpin.MustParse(args, err) { + case run.FullCommand(): + log.WithFields(log.Fields{ + "File": *runFile, + "Verbose": *verbose, + }).Debug("Received run command") + + runFromFile() + case interactive.FullCommand(): + startRepl() + } +} + + + + +*/ diff --git a/cmd/run.go b/cmd/run.go new file mode 100644 index 0000000..3989ffe --- /dev/null +++ b/cmd/run.go @@ -0,0 +1,109 @@ +package cmd + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/ttacon/chalk" + + "github.com/hussar-lang/hussar/evaluator" + "github.com/hussar-lang/hussar/lexer" + "github.com/hussar-lang/hussar/object" + "github.com/hussar-lang/hussar/parser" +) + +var run = &cobra.Command{ + Use: "run", + Short: "Run the given script", + Run: func(cmd *cobra.Command, args []string) { + runFromFile() + }, +} + +func init() { + run.Flags().String("source.file", "", "the source file to run") + viper.BindPFlags(run.Flags()) +} + +func runFromFile() { + file, err := getSourceFile(viper.GetString("source.file")) + if err != nil { + log.Fatal(err) + } + + l := lexer.New(string(file)) + p := parser.New(l) + program := p.ParseProgram() + + if len(p.Errors()) != 0 { + printParserErrors(os.Stderr, p.Errors()) + os.Exit(1) + } + + env := object.NewEnvironment() + eval := evaluator.Eval(program, env) + if eval.Inspect() != "NULL" { + fmt.Println(eval.Inspect()) + } +} + +func getSourceFile(sourceFile string) ([]byte, error) { + if sourceFile == "" { + cwd, err := os.Getwd() + if err != nil { + log.WithError(err).Fatal() + } + + var files []string + filepath.Walk(cwd, func(path string, f os.FileInfo, _ error) error { + if !f.IsDir() { + if filepath.Ext(path) == "hss" { + files = append(files, f.Name()) + } + } + return nil + }) + + if len(files) == 0 { + log.WithError(errors.New("no source files found in current directory")).Fatal() + } else if len(files) > 1 { + for _, f := range files { + if strings.ToLower(f) == "main.hss" { + sourceFile = f + break + } + } + + // Hack, I know + if sourceFile == "" { + log.WithError(errors.New("no main source file found in current directory - specify one with the source.file flag")).Fatal() + } + } else { + sourceFile = files[0] + } + } + + source, err := ioutil.ReadFile(sourceFile) + if err != nil { + log.Fatal(err) + } + + return source, nil +} + +func printParserErrors(out io.Writer, errors []string) { + errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style + + io.WriteString(out, errColor("PARSER ERROR!\n")) + for _, msg := range errors { + io.WriteString(out, errColor(" [!] ")+msg+"\n") + } +} diff --git a/main.go b/main.go index 19027e2..81785d6 100644 --- a/main.go +++ b/main.go @@ -1,96 +1,15 @@ package main import ( - "fmt" - "io" - "io/ioutil" - "os" - - "github.com/hussar-lang/hussar/evaluator" - "github.com/hussar-lang/hussar/lexer" - "github.com/hussar-lang/hussar/object" - "github.com/hussar-lang/hussar/parser" - "github.com/hussar-lang/hussar/repl" - - log "github.com/sirupsen/logrus" - "github.com/ttacon/chalk" - "gopkg.in/alecthomas/kingpin.v2" + "github.com/hussar-lang/hussar/cmd" ) var ( GitCommit string VersionString string - - app = kingpin.New("hussar", "The Hussar interpreter") - verbose = app.Flag("verbose", "Enable verbose logging.").Short('v').Bool() - - // TODO: run interactive mode if no subcommand was given (see #1) - interactive = app.Command("interactive", "Interactive REPL") - - run = app.Command("run", "Run Hussar code") - runFile = run.Flag("file", "Code to run").Required().Short('f').ExistingFile() ) -func init() { - log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) - log.SetOutput(os.Stdout) -} - func main() { - app.Version(fmt.Sprintf("%s (%s)", VersionString, GitCommit)) - args, err := app.Parse(os.Args[1:]) - - if *verbose { - log.SetLevel(log.DebugLevel) - } else { - log.SetLevel(log.WarnLevel) - } - - switch kingpin.MustParse(args, err) { - case run.FullCommand(): - log.WithFields(log.Fields{ - "File": *runFile, - "Verbose": *verbose, - }).Debug("Received run command") - - runFromFile() - case interactive.FullCommand(): - startRepl() - } -} - -func runFromFile() { - file, err := ioutil.ReadFile(*runFile) - if err != nil { - log.Fatal(err) - } - - l := lexer.New(string(file)) - p := parser.New(l) - program := p.ParseProgram() - - if len(p.Errors()) != 0 { - printParserErrors(os.Stdout, p.Errors()) - os.Exit(21) - } - - env := object.NewEnvironment() - eval := evaluator.Eval(program, env) - if eval.Inspect() != "NULL" { - fmt.Println(eval.Inspect()) - } -} - -func startRepl() { - fmt.Printf("Starting Hussar interactive interpreter v%s\n", VersionString) - repl.Start(os.Stdin, os.Stdout) -} - -func printParserErrors(out io.Writer, errors []string) { - errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style - - io.WriteString(out, errColor("PARSER ERROR!\n")) - for _, msg := range errors { - io.WriteString(out, errColor(" [!] ")+msg+"\n") - } + cmd.Setup(VersionString, GitCommit) + cmd.Execute() } From db115b4e4963c4c32f97b0f98d4188a697cf9b0d Mon Sep 17 00:00:00 2001 From: kscarlett Date: Thu, 30 Aug 2018 15:30:30 +0100 Subject: [PATCH 3/5] fix(tools): Fix formatting on 'env' subcommand output --- cmd/env.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/env.go b/cmd/env.go index 8674731..9eab6ab 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -17,10 +17,10 @@ var env = &cobra.Command{ } func printEnvironment() { - fmt.Printf("arch: %s", runtime.GOARCH) - fmt.Printf("os: %s", runtime.GOOS) - fmt.Printf("bin: %s", os.Args[0]) - fmt.Printf("gc: %s", runtime.Version()) - fmt.Printf("vers: %s", version) - fmt.Printf("build: %s", build) + fmt.Printf("arch: %s\n", runtime.GOARCH) + fmt.Printf("os: %s\n", runtime.GOOS) + fmt.Printf("bin: %s\n", os.Args[0]) + fmt.Printf("gc: %s\n", runtime.Version()) + fmt.Printf("vers: %s\n", version) + fmt.Printf("build: %s\n", build) } From 757beea4a8e55494bdb196937f0ab2363dafa41d Mon Sep 17 00:00:00 2001 From: kscarlett Date: Thu, 30 Aug 2018 15:39:19 +0100 Subject: [PATCH 4/5] style(tools): Remove unneeded comment --- cmd/root.go | 64 ----------------------------------------------------- 1 file changed, 64 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 424ef90..9636eeb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -72,67 +72,3 @@ func initialize() { log.SetFormatter(&log.TextFormatter{}) } } - -/*import ( - "fmt" - "io" - "io/ioutil" - "os" - - "github.com/hussar-lang/hussar/evaluator" - "github.com/hussar-lang/hussar/lexer" - "github.com/hussar-lang/hussar/object" - "github.com/hussar-lang/hussar/parser" - "github.com/hussar-lang/hussar/repl" - - log "github.com/sirupsen/logrus" - "github.com/ttacon/chalk" - "gopkg.in/alecthomas/kingpin.v2" -) - -var ( - GitCommit string - VersionString string - - app = kingpin.New("hussar", "The Hussar interpreter") - verbose = app.Flag("verbose", "Enable verbose logging.").Short('v').Bool() - - // TODO: run interactive mode if no subcommand was given (see #1) - interactive = app.Command("interactive", "Interactive REPL") - - run = app.Command("run", "Run Hussar code") - runFile = run.Flag("file", "Code to run").Required().Short('f').ExistingFile() -) - -func init() { - log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) - log.SetOutput(os.Stdout) -} - -func main() { - app.Version(fmt.Sprintf("%s (%s)", VersionString, GitCommit)) - args, err := app.Parse(os.Args[1:]) - - if *verbose { - log.SetLevel(log.DebugLevel) - } else { - log.SetLevel(log.WarnLevel) - } - - switch kingpin.MustParse(args, err) { - case run.FullCommand(): - log.WithFields(log.Fields{ - "File": *runFile, - "Verbose": *verbose, - }).Debug("Received run command") - - runFromFile() - case interactive.FullCommand(): - startRepl() - } -} - - - - -*/ From 7579b4b8cb3f2af316ec892e23113d1d1b8bd1ff Mon Sep 17 00:00:00 2001 From: kscarlett Date: Thu, 30 Aug 2018 15:48:04 +0100 Subject: [PATCH 5/5] ci(travis): Update Go versions for build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7a6401d..4e40dfa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,10 @@ matrix: include: - go: 1.x env: LATEST=true - - go: 1.7.x - go: 1.8.x - go: 1.9.x - go: 1.10.x + - go: 1.11.x - go: tip allow_failures: - go: tip