gopush

package module
v0.0.0-...-69a5de4 Latest Latest
Warning

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

Go to latest
Published: Jun 6, 2017 License: MIT Imports: 12 Imported by: 1

README

Status: This project is abandoned. I'm keeping it online because it may still prove to be useful for someone, but I will not address Issues or merge Pull requests.

gopush

Coverage Status GoDoc

gopush is an implementation of the Push 3.0 programming language in Go.

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

Examples

Constants

This section is empty.

Variables

View Source
var DefaultOptions, _ = ParseOptions(defaultConfigFile)

DefaultOptions contains the default configuration for a Push Interpreter.

Functions

This section is empty.

Types

type Code

type Code struct {
	Length  int
	Literal string
	List    []Code
}

Code is the internal list representation of a (partial) Push program.

func ParseCode

func ParseCode(program string) (c Code, err error)

ParseCode takes the provided Push program and parses it into the internal list representation (type Code).

func (Code) Container

func (c Code) Container(c2 Code) (container Code)

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

func (c Code) Contains(c2 Code) bool

Contains returns whether the Code c is equal to c2 or contains it in any sublist

func (Code) String

func (c Code) String() string

func (Code) UniqueItems

func (c Code) UniqueItems() map[string]int64

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

func (*Interpreter) StackOK

func (i *Interpreter) StackOK(name string, mindepth int64) bool

StackOK verifies that the given stack exists and has at least `mindepth` elements on it. This is used in stack functions to check if enough operands are available to carry out an instruction.

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

func ParseOptions(s string) (Options, error)

ParseOptions parses the given string into the Options struct.

func ReadOptions

func ReadOptions(r io.Reader) (Options, error)

ReadOptions reads a configuration file from the given io.Reader and returns the corresponding Options struct

func ReadOptionsFromFile

func ReadOptionsFromFile(filename string) (Options, error)

ReadOptionsFromFile reads the given configuration file and returns the corresponding Options struct

func (Options) RegisterStack

func (o Options) RegisterStack(name string, s *Stack)

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) Dup

func (s *Stack) Dup()

Dup duplicates the item on top of the stack.

func (*Stack) Flush

func (s *Stack) Flush()

Flush empties the stack

func (Stack) Len

func (s Stack) Len() int64

Len returns the number of items on the stack.

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.

func (*Stack) Shove

func (s *Stack) Shove(item interface{}, idx int64)

Shove inserts an item deep into the stack, at index idx.

func (*Stack) Swap

func (s *Stack) Swap()

Swap swaps the top two items on the stack.

func (*Stack) Yank

func (s *Stack) Yank(idx int64)

Yank pulls out an item deep in the stack, at index idx, and puts it on top of the stack.

func (*Stack) YankDup

func (s *Stack) YankDup(idx int64)

YankDup copies an item deep in the stack, at index ids, and puts the copy on top of the stack.

Jump to

Keyboard shortcuts

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