<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/nitrogen-lang/nitrogen/src/compiler"
	"github.com/nitrogen-lang/nitrogen/src/eval"
	"github.com/nitrogen-lang/nitrogen/src/lexer"
	"github.com/nitrogen-lang/nitrogen/src/moduleutils"
	"github.com/nitrogen-lang/nitrogen/src/object"
	"github.com/nitrogen-lang/nitrogen/src/parser"
	"github.com/nitrogen-lang/nitrogen/src/vm"

	_ "github.com/nitrogen-lang/nitrogen/src/builtins"
)

const (
	interactivePrompt = ">> "
	version           = "0.1.0"
)

var (
	interactive       bool
	printAst          bool
	startSCGI         bool
	scgiSock          string
	scgiWorkers       int
	scgiWorkerTimeout int
	modulePath        string
	printVersion      bool
	fullDebug         bool
	compile           bool
)

func init() {
	flag.BoolVar(&interactive, "i", false, "Interactive mode")
	flag.BoolVar(&printAst, "ast", false, "Print AST and exit")
	flag.BoolVar(&startSCGI, "scgi", false, "Start as an SCGI server")
	flag.StringVar(&scgiSock, "scgi-sock", "tcp:0.0.0.0:9000", "Socket to listen on for SCGI")
	flag.IntVar(&scgiWorkers, "scgi-workers", 5, "Number of workers to service SCGI requests")
	flag.IntVar(&scgiWorkerTimeout, "scgi-worker-timeout", 10, "Number of seconds to wait for an available worker before giving up")
	flag.StringVar(&modulePath, "modules", "", "Module directory")
	flag.BoolVar(&printVersion, "version", false, "Print version information")
	flag.BoolVar(&fullDebug, "debug", false, "Enable debug mode")
	flag.BoolVar(&compile, "compile", false, "Use the Nitrogen VM")
}

func main() {
	flag.Parse()

	if printVersion {
		fmt.Printf("Nitrogen Interpreter Version %s\n", version)
		return
	}

	modulesPath := os.Getenv("NITROGEN_MODULES")
	if modulePath != "" {
		modulesPath = modulePath
	}
	if modulesPath != "" {
		if err := loadModules(modulesPath); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	if startSCGI {
		startSCGIServer()
		return
	}

	moduleutils.ParserSettings.Debug = fullDebug
	if interactive {
		fmt.Print("Nitrogen Programming Language\n")
		fmt.Print("Type in commands at the prompt\n")
		startRepl(os.Stdin, os.Stdout)
		return
	}

	if flag.NArg() == 0 {
		fmt.Print("No script given")
		os.Exit(1)
	}

	program, err := moduleutils.ASTCache.GetTree(flag.Arg(0))
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	if printAst {
		fmt.Println(program.String())
		os.Exit(1)
	}

	if compile {
		code := compiler.Compile(program, "__main")
		if fullDebug {
			code.Print("")
		}

		env := object.NewEnvironment()
		env.CreateConst("_ENV", getEnvironment())
		env.CreateConst("_ARGV", getScriptArgs(flag.Arg(0)))
		env.CreateConst("_FILE", object.MakeStringObj(code.Filename))

		vmsettings := vm.NewSettings()
		vmsettings.Debug = fullDebug
		machine := vm.NewVM(vmsettings)

		start := time.Now()
		result := machine.Execute(code, env)

		if fullDebug {
			fmt.Printf("Execution took %s\n", time.Now().Sub(start))
		}

		if result != nil && result != object.NullConst {
			if e, ok := result.(*object.Exception); ok {
				os.Stdout.WriteString("Uncaught Exception: ")
				os.Stdout.WriteString(e.Message)
				os.Stdout.Write([]byte{'\n'})
				os.Exit(1)
			}
			os.Stdout.WriteString(result.Inspect())
			os.Stdout.Write([]byte{'\n'})
		}
		return
	}

	env := object.NewEnvironment()
	env.CreateConst("_ENV", getEnvironment())

	env.CreateConst("_ARGV", getScriptArgs(flag.Arg(0)))

	interpreter := eval.NewInterpreter()
	start := time.Now()
	result := interpreter.Eval(program, env)
	if fullDebug {
		fmt.Printf("Execution took %s\n", time.Now().Sub(start))
	}
	if result != nil && result != object.NullConst {
		if e, ok := result.(*object.Exception); ok {
			os.Stdout.WriteString("Uncaught Exception: ")
			os.Stdout.WriteString(e.Message)
			os.Stdout.Write([]byte{'\n'})
			os.Exit(1)
		}
		os.Stdout.WriteString(result.Inspect())
		os.Stdout.Write([]byte{'\n'})
	}
}

func getEnvironment() *object.Hash {
	return makeEnvironment(getEnvironmentMap())
}

func getEnvironmentMap() map[string]string {
	env := os.Environ()
	m := make(map[string]string, len(env))
	for _, v := range env {
		val := strings.SplitN(v, "=", 2)
		m[val[0]] = val[1]
	}
	return m
}<commit_msg>Cleaned up starting execution<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/nitrogen-lang/nitrogen/src/compiler"
	"github.com/nitrogen-lang/nitrogen/src/eval"
	"github.com/nitrogen-lang/nitrogen/src/lexer"
	"github.com/nitrogen-lang/nitrogen/src/moduleutils"
	"github.com/nitrogen-lang/nitrogen/src/object"
	"github.com/nitrogen-lang/nitrogen/src/parser"
	"github.com/nitrogen-lang/nitrogen/src/vm"

	_ "github.com/nitrogen-lang/nitrogen/src/builtins"
)

const (
	interactivePrompt = ">> "
	version           = "0.1.0"
)

var (
	interactive       bool
	printAst          bool
	startSCGI         bool
	scgiSock          string
	scgiWorkers       int
	scgiWorkerTimeout int
	modulePath        string
	printVersion      bool
	fullDebug         bool
	compile           bool
)

func init() {
	flag.BoolVar(&interactive, "i", false, "Interactive mode")
	flag.BoolVar(&printAst, "ast", false, "Print AST and exit")
	flag.BoolVar(&startSCGI, "scgi", false, "Start as an SCGI server")
	flag.StringVar(&scgiSock, "scgi-sock", "tcp:0.0.0.0:9000", "Socket to listen on for SCGI")
	flag.IntVar(&scgiWorkers, "scgi-workers", 5, "Number of workers to service SCGI requests")
	flag.IntVar(&scgiWorkerTimeout, "scgi-worker-timeout", 10, "Number of seconds to wait for an available worker before giving up")
	flag.StringVar(&modulePath, "modules", "", "Module directory")
	flag.BoolVar(&printVersion, "version", false, "Print version information")
	flag.BoolVar(&fullDebug, "debug", false, "Enable debug mode")
	flag.BoolVar(&compile, "compile", false, "Use the Nitrogen VM")
}

func main() {
	flag.Parse()

	if printVersion {
		fmt.Printf("Nitrogen Interpreter Version %s\n", version)
		return
	}

	modulesPath := os.Getenv("NITROGEN_MODULES")
	if modulePath != "" {
		modulesPath = modulePath
	}
	if modulesPath != "" {
		if err := loadModules(modulesPath); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	if startSCGI {
		startSCGIServer()
		return
	}

	moduleutils.ParserSettings.Debug = fullDebug
	if interactive {
		fmt.Print("Nitrogen Programming Language\n")
		fmt.Print("Type in commands at the prompt\n")
		startRepl(os.Stdin, os.Stdout)
		return
	}

	if flag.NArg() == 0 {
		fmt.Print("No script given")
		os.Exit(1)
	}

	program, err := moduleutils.ASTCache.GetTree(flag.Arg(0))
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	if printAst {
		fmt.Println(program.String())
		os.Exit(1)
	}

	env := object.NewEnvironment()
	env.CreateConst("_ENV", getEnvironment())
	env.CreateConst("_ARGV", getScriptArgs(flag.Arg(0)))

	var result object.Object
	var start time.Time
	if compile {
		code := compiler.Compile(program, "__main")
		if fullDebug {
			code.Print("")
		}

		env.CreateConst("_FILE", object.MakeStringObj(code.Filename))

		vmsettings := vm.NewSettings()
		vmsettings.Debug = fullDebug
		machine := vm.NewVM(vmsettings)

		start = time.Now()
		result = machine.Execute(code, env)
	} else {
		interpreter := eval.NewInterpreter()

		start = time.Now()
		result = interpreter.Eval(program, env)
	}

	if fullDebug {
		fmt.Printf("Execution took %s\n", time.Now().Sub(start))
	}

	if result != nil && result != object.NullConst {
		if e, ok := result.(*object.Exception); ok {
			os.Stdout.WriteString("Uncaught Exception: ")
			os.Stdout.WriteString(e.Message)
			os.Stdout.Write([]byte{'\n'})
			os.Exit(1)
		}
		os.Stdout.WriteString(result.Inspect())
		os.Stdout.Write([]byte{'\n'})
	}
}

func getEnvironment() *object.Hash {
	return makeEnvironment(getEnvironmentMap())
}

func getEnvironmentMap() map[string]string {
	env := os.Environ()
	m := make(map[string]string, len(env))
	for _, v := range env {
		val := strings.SplitN(v, "=", 2)
		m[val[0]] = val[1]
	}
	return m
}
{'fraction_non_alphanumeric': 0.15583114117499686, 'fraction_numerical': 0.006263309532757109, 'mean_word_length': 3.8831804281345565, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5252120', 'n_tokens_mistral': 3067, 'n_tokens_neox': 2886, 'n_words': 576}