-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
232 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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\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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
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{}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |