goal

package
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2026 License: BSD-3-Clause Imports: 24 Imported by: 1

README

Goal: Go augmented language

Goal is an augmented version of the Go language, which combines the best parts of Go, bash, and Python, to provide and integrated shell and numerical expression processing experience, which can be combined with the yaegi interpreter to provide an interactive "REPL" (read, evaluate, print loop).

See the Cogent Lab Docs for full documentation.

Design discussion

Goal transpiles directly into Go, so it automatically leverages all the great features of Go, and remains fully compatible with it. The augmentation is designed to overcome some of the limitations of Go in specific domains:

  • Shell scripting, where you want to be able to directly call other executable programs with arguments, without having to navigate all the complexity of the standard os.exec package.

  • Numerical / math / data processing, where you want to be able to write simple mathematical expressions operating on vectors, matricies and other more powerful data types, without having to constantly worry about numerical type conversions, and advanced n-dimensional indexing and slicing expressions are critical. Python is the dominant language here precisely because it lets you ignore type information and write such expressions, using operator overloading.

  • GPU-based parallel computation, which can greatly speed up some types of parallelizable computations by effectively running many instances of the same code in parallel across a large array of data. The gosl package (automatically run in goal build mode) allows you to run the same Go-based code on a GPU or CPU (using parallel goroutines). See the GPU docs for an overview and comparison to other approaches to GPU computation.

The main goal of Goal is to achieve a "best of both worlds" solution that retains all the type safety and explicitness of Go for all the surrounding control flow and large-scale application logic, while also allowing for a more relaxed syntax in specific, well-defined domains where the Go language has been a barrier. Thus, unlike Python where there are various weak attempts to try to encourage better coding habits, Goal retains in its Go foundation a fundamentally scalable, "industrial strength" language that has already proven its worth in countless real-world applications.

For the shell scripting aspect of Goal, the simple idea is that each line of code is either Go or shell commands, determined in a fairly intuitive way mostly by the content at the start of the line (formal rules below). If a line starts off with something like ls -la... then it is clear that it is not valid Go code, and it is therefore processed as a shell command.

You can intermix Go within a shell line by wrapping an expression with { } braces, and a Go expression can contain shell code by using $. Here's an example:

for i, f := range goalib.SplitLines($ls -la$) {  // ls executes, returns string
    echo {i} {strings.ToLower(f)}              // {} surrounds Go within shell
}

where goalib.SplitLines is a function that runs strings.Split(arg, "\n"), defined in the goalib standard library of such frequently-used helper functions.

For cases where most of the code is standard Go with relatively infrequent use of shell expressions, or in the rare cases where the default interpretation doesn't work, you can explicitly tag a line as shell code using $:

$ chmod +x *.goal

For mathematical expressions, we use # symbols (# = number) to demarcate such expressions. Often you will write entire lines of such expressions:

# x := 1. / (1. + exp(-wts[:, :, :n] * acts[:]))

You can also intermix within Go code:

for _, x := range #[1,2,3]# {
    fmt.Println(#x^2#)
}

Note that you cannot enter math mode directly from shell mode, which is unlikely to be useful anyway (you can wrap in go mode { } if really needed).

In general, the math mode syntax in Goal is designed to be as compatible with Python NumPy / SciPy syntax as possible, while also adding a few Go-specific additions as well: see the Math mode section for details. All elements of a Goal math expression are tensors, which can represent everything from a scalar to an n-dimenstional tensor. These are called "ndarray" in NumPy terms.

The one special form of tensor processing that is available in regular Go code is n dimensional indexing, e.g., tsr[1,2]. This kind of expression with square brackets [ ] and a comma is illegal according to standard Go syntax, so when we detect it, we know that it is being used on a tensor object, and can transpile it into the corresponding tensor.Value or tensor.Set* expression. This is particularly convenient for gosl GPU code that has special support for tensor data. Note that for this GPU use-case, you actually do not want to use math mode, because that engages a different, more complex form of indexing that does not work on the GPU.

The rationale and mnemonics for using $ and # are as follows:

  • These are two of the three common ASCII keyboard symbols that are not part of standard Go syntax (@ being the other).

  • $ can be thought of as "S" in _S_hell, and is often used for a bash prompt, and many bash examples use it as a prefix. Furthermore, in bash, $( ) is used to wrap shell expressions.

  • # is commonly used to refer to numbers. It is also often used as a comment syntax, but on balance the number semantics and uniqueness relative to Go syntax outweigh that issue.

Documentation

Overview

Package goal provides the Goal Go augmented language transpiler, which combines the best parts of Go, bash, and Python to provide an integrated shell and numerical expression processing experience.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddHomeExpand

func AddHomeExpand(list []string, adds ...string) []string

AddHomeExpand adds given strings to the given list of strings, expanding any ~ symbols with the home directory, and returns the updated list.

Types

type Goal

type Goal struct {

	// Config is the [exec.Config] used to run commands.
	Config exec.Config

	// StdIOWrappers are IO wrappers sent to the interpreter, so we can
	// control the IO streams used within the interpreter.
	// Call SetWrappers on this with another StdIO object to update settings.
	StdIOWrappers exec.StdIO

	// ssh connection, configuration
	SSH *sshclient.Config

	// collection of ssh clients
	SSHClients map[string]*sshclient.Client

	// SSHActive is the name of the active SSH client
	SSHActive string

	// Builtins are all the builtin shell commands
	Builtins map[string]func(cmdIO *exec.CmdIO, args ...string) error

	// commands that have been defined, which can be run in Exec mode.
	Commands map[string]func(args ...string)

	// Jobs is a stack of commands running in the background
	// (via Start instead of Run)
	Jobs stack.Stack[*Job]

	// Cancel, while the interpreter is running, can be called
	// to stop the code interpreting.
	// It is connected to the Ctx context, by StartContext()
	// Both can be nil.
	Cancel func()

	// Errors is a stack of runtime errors.
	Errors []error

	// CliArgs are input arguments from the command line.
	CliArgs []any

	// Ctx is the context used for cancelling current shell running
	// a single chunk of code, typically from the interpreter.
	// We are not able to pass the context around so it is set here,
	// in the StartContext function. Clear when done with ClearContext.
	Ctx context.Context

	// original standard IO setings, to restore
	OrigStdIO exec.StdIO

	// Hist is the accumulated list of command-line input,
	// which is displayed with the history builtin command,
	// and saved / restored from ~/.goalhist file
	Hist []string

	// transpiling state
	TrState transpile.State
	// contains filtered or unexported fields
}

Goal represents one running Goal language context.

func NewGoal

func NewGoal() *Goal

NewGoal returns a new Goal with default options.

func (*Goal) ActiveSSH

func (gl *Goal) ActiveSSH() *sshclient.Client

ActiveSSH returns the active ssh client

func (*Goal) AddCommand

func (gl *Goal) AddCommand(name string, cmd func(args ...string))

AddCommand adds given command to list of available commands.

func (*Goal) AddError

func (gl *Goal) AddError(err error) error

AddError adds the given error to the error stack if it is non-nil, and calls the Cancel function if set, to stop execution. This is the main way that goal errors are handled. It also prints the error.

func (*Goal) AddHistory

func (gl *Goal) AddHistory(line string)

AddHistory adds given line to the Hist record of commands

func (*Goal) AddPath

func (gl *Goal) AddPath(cmdIO *exec.CmdIO, args ...string) error

AddPath adds the given path(s) to $PATH.

func (*Goal) Args

func (gl *Goal) Args() []any

Args returns the command line arguments.

func (*Goal) CancelExecution

func (gl *Goal) CancelExecution()

CancelExecution calls the Cancel() function if set.

func (*Goal) Cd

func (gl *Goal) Cd(cmdIO *exec.CmdIO, args ...string) error

Cd changes the current directory.

func (*Goal) Close

func (gl *Goal) Close()

Close closes any resources associated with the shell, including terminating any commands that are not running "nohup" in the background.

func (*Goal) CloseSSH

func (gl *Goal) CloseSSH()

CloseSSH closes all open ssh client connections

func (*Goal) CmdArgs

func (gl *Goal) CmdArgs(errOk bool, sargs []string, i int) []string

CmdArgs processes expressions involving "args" for commands

func (*Goal) CompleteEdit

func (gl *Goal) CompleteEdit(data any, text string, cursorPos int, completion complete.Completion, seed string) (ed complete.Edit)

CompleteEdit is the complete.EditFunc for the shell.

func (*Goal) CompleteMatch

func (gl *Goal) CompleteMatch(data any, text string, posLine, posChar int) (md complete.Matches)

CompleteMatch is the complete.MatchFunc for the shell.

func (*Goal) Debug

func (gl *Goal) Debug(cmdIO *exec.CmdIO, args ...string) error

Debug changes log level

func (*Goal) DeleteAllJobs

func (gl *Goal) DeleteAllJobs()

DeleteAllJobs deletes any existing jobs, closing stdio.

func (*Goal) DeleteJob

func (gl *Goal) DeleteJob(job *Job) bool

DeleteJob deletes the given job and returns true if successful,

func (*Goal) EndContext

func (gl *Goal) EndContext()

EndContext ends a processing context, clearing the Ctx and Cancel fields.

func (*Goal) Exec

func (gl *Goal) Exec(errOk, start, output bool, cmd any, args ...any) string

Exec handles command execution for all cases, parameterized by the args. It executes the given command string, waiting for the command to finish, handling the given arguments appropriately. If there is any error, it adds it to the goal, and triggers CancelExecution.

  • errOk = don't call AddError so execution will not stop on error
  • start = calls Start on the command, which then runs asynchronously, with a goroutine forked to Wait for it and close its IO
  • output = return the output of the command as a string (otherwise return is "")

func (*Goal) ExecArgs

func (gl *Goal) ExecArgs(cmdIO *exec.CmdIO, errOk bool, cmd any, args ...any) (*sshclient.Client, string, []string)

ExecArgs processes the args to given exec command, handling all of the input / output redirection and file globbing, homedir expansion, etc.

func (*Goal) Exit

func (gl *Goal) Exit(cmdIO *exec.CmdIO, args ...string) error

Exit exits the shell.

func (*Goal) Fg

func (gl *Goal) Fg(cmdIO *exec.CmdIO, args ...string) error

Fg foregrounds a job by job number

func (*Goal) GoSSH

func (gl *Goal) GoSSH(cmdIO *exec.CmdIO, args ...string) error

GoSSH manages SSH connections, which are referenced by the @name identifier. It handles the following cases:

  • @name -- switches to using given host for all subsequent commands
  • host [name] -- connects to a server specified in first arg and switches to using it, with optional name instead of default sequential number.
  • close -- closes all open connections, or the specified one

func (*Goal) HandleArgErr

func (gl *Goal) HandleArgErr(errok bool, err error) error

func (*Goal) History

func (gl *Goal) History(cmdIO *exec.CmdIO, args ...string) error

History shows history

func (*Goal) Host

func (gl *Goal) Host() string

Host returns the name we're running commands on, which is empty if localhost (default).

func (*Goal) HostAndDir

func (gl *Goal) HostAndDir() string

HostAndDir returns the name we're running commands on, which is empty if localhost (default), and the current directory on that host.

func (*Goal) InstallBuiltins

func (gl *Goal) InstallBuiltins()

InstallBuiltins adds the builtin goal commands to [Goal.Builtins].

func (*Goal) JobIDExpand

func (gl *Goal) JobIDExpand(args []string) int

JobIDExpand expands %n job id values in args with the full PID returns number of PIDs expanded

func (*Goal) JobsCmd

func (gl *Goal) JobsCmd(cmdIO *exec.CmdIO, args ...string) error

JobsCmd is the builtin jobs command

func (*Goal) Kill

func (gl *Goal) Kill(cmdIO *exec.CmdIO, args ...string) error

Kill kills a job by job number or PID. Just expands the job id expressions %n into PIDs and calls system kill.

func (*Goal) OpenHistory

func (gl *Goal) OpenHistory(file string) error

OpenHistory opens Hist history lines from given file, e.g., ~/.goalhist

func (*Goal) OutToFile

func (gl *Goal) OutToFile(cl *sshclient.Client, cmdIO *exec.CmdIO, errOk bool, sargs []string, i int) []string

OutToFile processes the > arg that sends output to a file

func (*Goal) OutToPipe

func (gl *Goal) OutToPipe(cl *sshclient.Client, cmdIO *exec.CmdIO, errOk bool, sargs []string, i int) []string

OutToPipe processes the | arg that sends output to a pipe

func (*Goal) Output

func (gl *Goal) Output(cmd any, args ...any) string

Output executes the given command string, handling the given arguments appropriately. If there is any error, it adds it to the goal. It returns the stdout as a string and forwards stderr to exec.Config.Stderr appropriately.

func (*Goal) OutputErrOK

func (gl *Goal) OutputErrOK(cmd any, args ...any) string

OutputErrOK executes the given command string, handling the given arguments appropriately. If there is any error, it adds it to the goal. It returns the stdout as a string and forwards stderr to exec.Config.Stderr appropriately.

func (*Goal) RestoreOrigStdIO

func (gl *Goal) RestoreOrigStdIO()

RestoreOrigStdIO reverts to using the saved OrigStdIO

func (*Goal) Run

func (gl *Goal) Run(cmd any, args ...any)

Run executes the given command string, waiting for the command to finish, handling the given arguments appropriately. If there is any error, it adds it to the goal, and triggers CancelExecution. It forwards output to exec.Config.Stdout and exec.Config.Stderr appropriately.

func (*Goal) RunBuiltinOrCommand

func (gl *Goal) RunBuiltinOrCommand(cmdIO *exec.CmdIO, errOk, start, output bool, cmd string, args ...string) (bool, string)

RunBuiltinOrCommand runs a builtin or a command, returning true if it ran, and the output string if running in output mode.

func (*Goal) RunCommands

func (gl *Goal) RunCommands(cmds []any) error

RunCommands runs the given command(s). This is typically called from a Makefile-style goal script.

func (*Goal) RunErrOK

func (gl *Goal) RunErrOK(cmd any, args ...any)

RunErrOK executes the given command string, waiting for the command to finish, handling the given arguments appropriately. It does not stop execution if there is an error. If there is any error, it adds it to the goal. It forwards output to exec.Config.Stdout and exec.Config.Stderr appropriately.

func (*Goal) SSHByHost

func (gl *Goal) SSHByHost(host string) (*sshclient.Client, error)

SSHByHost returns the SSH client for given host name, with err if not found

func (*Goal) SaveHistory

func (gl *Goal) SaveHistory(n int, file string) error

SaveHistory saves up to the given number of lines of current history to given file, e.g., ~/.goalhist for the default goal program. If n is <= 0 all lines are saved. n is typically 500 by default.

func (*Goal) SaveOrigStdIO

func (gl *Goal) SaveOrigStdIO()

SaveOrigStdIO saves the current Config.StdIO as the original to revert to after an error, and sets the StdIOWrappers to use them.

func (*Goal) Scp

func (gl *Goal) Scp(cmdIO *exec.CmdIO, args ...string) error

Scp performs file copy over SSH connection, with the remote filename prefixed with the @name: and the local filename un-prefixed. The order is from -> to, as in standard cp. The remote filename is automatically relative to the current working directory on the remote host.

func (*Goal) Set

func (gl *Goal) Set(cmdIO *exec.CmdIO, args ...string) error

Set sets the given environment variable to the given value.

func (*Goal) Source

func (gl *Goal) Source(cmdIO *exec.CmdIO, args ...string) error

Source loads and evaluates the given file(s)

func (*Goal) Start

func (gl *Goal) Start(cmd any, args ...any)

Start starts the given command string for running in the background, handling the given arguments appropriately. If there is any error, it adds it to the goal. It forwards output to exec.Config.Stdout and exec.Config.Stderr appropriately.

func (*Goal) StartContext

func (gl *Goal) StartContext() context.Context

StartContext starts a processing context, setting the Ctx and Cancel Fields. Call EndContext when current operation finishes.

func (*Goal) TranspileCode

func (gl *Goal) TranspileCode(code string)

TranspileCode processes each line of given code, adding the results to the LineStack

func (*Goal) TranspileCodeFromFile

func (gl *Goal) TranspileCodeFromFile(file string) error

TranspileCodeFromFile transpiles the code in given file

func (*Goal) TranspileConfig

func (gl *Goal) TranspileConfig() error

TranspileConfig transpiles the .goal startup config file in the user's home directory if it exists.

func (*Goal) TranspileFile

func (gl *Goal) TranspileFile(in string, out string) error

TranspileFile transpiles the given input goal file to the given output Go file. If no existing package declaration is found, then package main and func main declarations are added. This also affects how functions are interpreted.

func (*Goal) Unset

func (gl *Goal) Unset(cmdIO *exec.CmdIO, args ...string) error

Unset un-sets the given environment variable.

func (*Goal) Which

func (gl *Goal) Which(cmdIO *exec.CmdIO, args ...string) error

Which reports the executable associated with the given command. Processes builtins and commands, and if not found, then passes on to exec which.

type Job

type Job struct {
	*exec.CmdIO
	IsExec  bool
	GotPipe bool
}

Job represents a job that has been started and we're waiting for it to finish.

type ReadlineCompleter

type ReadlineCompleter struct {
	Goal *Goal
}

ReadlineCompleter implements github.com/cogentcore/readline.AutoCompleter.

func (*ReadlineCompleter) Do

func (rc *ReadlineCompleter) Do(line []rune, pos int) (newLine [][]rune, length int)

Directories

Path Synopsis
cmd
goal command
Command goal is an interactive cli for running and compiling Goal code.
Command goal is an interactive cli for running and compiling Goal code.
Package goalib defines convenient utility functions for use in the goal shell, available with the goalib prefix.
Package goalib defines convenient utility functions for use in the goal shell, available with the goalib prefix.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL