Documentation
¶
Overview ¶
Package gopush provides an interpreter for the Push 3.0 programming language.
To create a new Interpreter, you must first specify a set of Options, or use the provided DefaultOptions:
options := gopush.DefaultOptions interpreter := gopush.NewInterpreter(options)
You can provide custom data types and associated behavior by implementing a new Stack object:
printStack := &gopush.Stack{ Functions: make(map[string]func()) } printStack.Functions["hello"] = func() { fmt.Println("hello") }
The keys of the Functions map *must* be lowercase. For more information on stacks, take a look at the builtin stacks in the stack_* files.
After creating your new data type, you need to register it with Interpreter to make it usable.
stackName := "print" interpreter.Options.RegisterStack(stackName, printStack) interpreter.RegisterStack(stackName, printStack)
The first RegisterStack call adds all instructions from printStack to the list of allowed instructions. The second RegisterStack call adds printStack and its instructions to the Interpreter so they can be used. This double-registration is not ideal, and I would welcome suggestions on how to remedy it without losing the ability to mark certain instructions as disallowed.
Finally, you can run the interpreter to execute a given program:
program := "PRINT.HELLO" interpreter.Run(program)
Alternatively you can parse the program into the Code representation and run that:
program := "PRINT.HELLO" c, err := ParseCode(program) if err != nil { // handle error } interpreter.RunCode(c)
Example ¶
package main import ( "fmt" "github.com/DataWraith/gopush" ) func main() { // Use the default options options := gopush.DefaultOptions // Instantiate a new interpreter interpreter := gopush.NewInterpreter(options) // Create a new data type printStack := &gopush.Stack{ Functions: make(map[string]func()), } // Add a function to the data type. This also demonstrates that // functions may have side effects outside of the interpreter when called. printStack.Functions["hello"] = func() { fmt.Println("hello") } // Register the new data type. The first statement adds the functions of // the type to the list of allowed functions, the second statement makes // the new type usable by the interpreter. interpreter.Options.RegisterStack("print", printStack) interpreter.RegisterStack("print", printStack) // Run the interpreter interpreter.Run("PRINT.HELLO") }
Output: hello
Index ¶
- Variables
- type Code
- type Interpreter
- type Options
- type Stack
- func (s *Stack) Dup()
- func (s *Stack) Flush()
- func (s Stack) Len() int64
- func (s Stack) Peek() interface{}
- func (s *Stack) Pop() (item interface{})
- func (s *Stack) Push(lit interface{})
- func (s *Stack) Rot()
- func (s *Stack) Shove(item interface{}, idx int64)
- func (s *Stack) Swap()
- func (s *Stack) Yank(idx int64)
- func (s *Stack) YankDup(idx int64)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultOptions, _ = ParseOptions(defaultConfigFile)
DefaultOptions contains the default configuration for a Push Interpreter.
Functions ¶
This section is empty.
Types ¶
type Code ¶
Code is the internal list representation of a (partial) Push program.
func ParseCode ¶
ParseCode takes the provided Push program and parses it into the internal list representation (type Code).
func (Code) Container ¶
Container returns the "container" of the given Code c2 in c. That is, it returns the smallest sublist of c which contains c2, or the empty list if none of the sublists in c contain c2.
func (Code) Contains ¶
Contains returns whether the Code c is equal to c2 or contains it in any sublist
func (Code) UniqueItems ¶
UniqueItems returns a map with the count of all unique items in the Code list
type Interpreter ¶
type Interpreter struct { Stacks map[string]*Stack Options Options Rand *rand.Rand Definitions map[string]Code // contains filtered or unexported fields }
Interpreter is a Push interpreter.
func NewInterpreter ¶
func NewInterpreter(options Options) *Interpreter
NewInterpreter returns a new Push Interpreter, configured with the provided Options.
func (*Interpreter) RandomCode ¶
func (i *Interpreter) RandomCode(maxPoints int64) Code
RandomCode implements the standard Push random code generation algorithm described at http://faculty.hampshire.edu/lspector/push3-description.html#RandomCode
func (*Interpreter) RegisterStack ¶
func (i *Interpreter) RegisterStack(name string, s *Stack)
RegisterStack registers the given stack under the given name. This automatically prunes instructions that are not in the set of allowed instructions and also makes the instructions of the stack available for CODE.RAND to generate. It will NOT overwrite already existing stacks.
func (*Interpreter) Run ¶
func (i *Interpreter) Run(program string) error
Run runs the given program written in the Push programming language until the EvalPushLimit is reached
func (*Interpreter) RunCode ¶
func (i *Interpreter) RunCode(c Code) error
RunCode runs the given program (given as Code type) until the EvalPushLimit is reached
type Options ¶
type Options struct { // When TRUE (which is the default), code passed to the top level of the // interpreter will be pushed onto the CODE stack prior to execution. TopLevelPushCode bool // When TRUE, the CODE stack will be popped at the end of top level // calls to the interpreter. The default is FALSE. TopLevelPopCode bool // The maximum number of points that will be executed in a single // top-level call to the interpreter. EvalPushLimit int // The probability that the selection of the ephemeral random NAME // constant for inclusion in randomly generated code will produce a new // name (rather than a name that was previously generated). NewERCNameProbabilty float64 // The maximum number of points that can occur in any program on the // CODE stack. Instructions that would violate this limit act as NOOPs. MaxPointsInProgram int // The maximum number of points in an expression produced by the // CODE.RAND instruction. MaxPointsInRandomExpression int64 // The maximum FLOAT that will be produced as an ephemeral random FLOAT // constant or from a call to FLOAT.RAND. MaxRandomFloat float64 // The minimum FLOAT that will be produced as an ephemeral random FLOAT // constant or from a call to FLOAT.RAND. MinRandomFloat float64 // The maximum INTEGER that will be produced as an ephemeral random // INTEGER constant or from a call to INTEGER.RAND. MaxRandomInteger int64 // The minimum INTEGER that will be produced as an ephemeral random // INTEGER constant or from a call to INTEGER.RAND. MinRandomInteger int64 // When TRUE the interpreter will print out the stacks after every // executed instruction Tracing bool // A seed for the random number generator. RandomSeed int64 // AllowedTypes lists the types (stacks) that are allowed AllowedTypes map[string]struct{} // AllowedInstructions lists the instructions that are allowed AllowedInstructions map[string]struct{} }
Options holds the configuration options for a Push Interpreter
func ParseOptions ¶
ParseOptions parses the given string into the Options struct.
func ReadOptions ¶
ReadOptions reads a configuration file from the given io.Reader and returns the corresponding Options struct
func ReadOptionsFromFile ¶
ReadOptionsFromFile reads the given configuration file and returns the corresponding Options struct
func (Options) RegisterStack ¶
RegisterStack adds all instructions from the given Stack to the list of allowed instructions
type Stack ¶
type Stack struct { Stack []interface{} Functions map[string]func() }
Stack represents a data type in the Push language. It contains the actual stack of values of that data type and a map of functions that pertain to that data type.
func (Stack) Peek ¶
func (s Stack) Peek() interface{}
Peek returns the topmost item on the stack, or an empty struct if the stack is empty.
func (*Stack) Pop ¶
func (s *Stack) Pop() (item interface{})
Pop pops an element off the stack. It returns an empty struct if the stack is empty.
func (*Stack) Push ¶
func (s *Stack) Push(lit interface{})
Push pushes a new element onto the stack.
func (*Stack) Rot ¶
func (s *Stack) Rot()
Rot rotates the top three stack items by pulling out the third item and pushing it on top.