gopherscript

package module
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2022 License: MIT Imports: 22 Imported by: 0

README

Gopherscript

Gopherscript is a secure scripting/configuration language written in Go. It features a fined-grain permission system and enforces a strong isolation of dependencies. Gopherscript is not production ready yet : if you find a bug or want to suggest a feature create an issue please ! Expect breaking changes.

Join the official community on Revolt.

image

Security & Minimalism

  • The codebase is small on purpose (a single Go file with less than 10K lines and only std lib dependencies). See Implementation.
  • The default global scope has ZERO variables/functions and there are no "builtin modules" to import. (only add what you need from Golang)
  • A strict but extensive permission system allows you to precisely control what is allowed (almost no permissions by default). For more details go to the permission section.
  • Paths, path patterns, URLs are literals and dynamic paths are only possible as path expressions. You cannot create them from strings at runtime ! That facilitates the listing of permissions and helps static analysis.
  • Properties cannot be accessed with a dynamic name ( $obj[$name] ), only Go functions that are passed objects in can (you have to trust them anyway).
  • In a general way some features will be added (or refused) to limit code obfuscation.

If you find Gopherscript too restrictive don't worry ! A lax mode might be introduced in the future.

Have a look at the features section and the wiki !

Installation & Usage

You can use the gos executable to execute scripts or launch a REPL:

go install github.com/debloat-dev/Gopherscript/cmd/gos@v0.5.0

See the documentation here. You can also use Gopherscript as a library and only add whay you need to the global scope (see the example further below).

Editor support

If you use VSCode you can install the extension of ID xbsd.gopherscript . If you are a NeoVim user, check this repo please.

Example
Example of using Gopherscript as a library from Golang:
package main

import (
	gos "github.com/debloat-dev/Gopherscript"
	"log"
)

type User struct {
	Name string
}

func main() {
   	//we create a Context that contains the granted permissions
	grantedPerms := []gos.Permission{
		gos.GlobalVarPermission{gos.UsePerm, "*"},
	}
	ctx := gos.NewContext(grantedPerms, nil)

    	//we create the initial state with the globals we want to expose
    	//the state can be re used several times (and with different modules)
	state := gos.NewState(ctx, map[string]interface{}{
		"makeUser": func(ctx *gos.Context) User {
			return User{Name: "Bar"}
		},
	})

	mod, err := gos.ParseAndCheckModule(`
            # permissions must be requested at the top of the file AND granted
            require {
                use: {globals: "*"} 
            }
            a = 1
            user = makeUser()
            return [
                ($a + 2),
                $user.Name
            ]
        `, "")
	
	if err != nil {
		log.Panicln(err)
	}

	//we execute the script
	res, err := gos.Eval(mod, state)
	if err != nil {
		log.Panicln(err)
	}

	log.Printf("%#v", res)
}

You can learn more about the interactions between Gopherscript and Golang here.

Features

The most important features are described in this section. If you want to learn Gopherscript or want to know more details about specific features you can go on the wiki.

Permissions

Required permissions are specified at the top of each module (file).

image

There are several permission kinds: Create, Update, Read, Delete, Use, Consume, Provide. Some permission types are already provided: FilesystemPermission, HttpPermission, StackPermission, GlobalVarPermission. You can specify your own permissions by implementing the Permission interface (Golang).

type Permission interface {
	Kind() PermissionKind
	Includes(Permission) bool
}

Gopherscript also provides limitations to prevent a script to take all resources. In the example below writing to the filesystem is limited to 100 kB/s.

require {
    
    [...]

    limits: {
        "fs/write": 100kB/s
    }
}

Permissions can also be dropped.

drop-perms {
   read: {
       : https://*
   }
}
Special literals & expressions
# Path literals
/home/user/
./file.json

# Path expressions
/home/user/$dirpath$

# Path patterns support basic globbing (*, [set], ?) and prefixing (not both at the same time).
./data/*.json
/app/logs/...
/app/*/...     		# invalid (this might be allowed in the future though)

# HTTP host literals
https://example.com
https://example.com:443

# HTTP host pattern literals
https://*               # any HTTPS host
https://*.com           # any domain with .com as TLD, will not match against subdomains
https://*.example.com   # any subdomain of example.com

# URL literals
https://example.com/
https://example.com/index.html
https://localhost/

# URL expressions
https://example.com/users/$id$
@loc/index.html       	# @loc is a host alias : the expression resolves to https://localhost/index.html if @loc = https://localhost


# URL pattern literals (only prefix patterns supported)
https://example.com/users/...
Quantity literals
10s		# time.Duration
10ms		# time.Duration
10%		# 0.10

sleep 100ms
Imports

Syntax:

import <varname> <url> <file-content-sha256>  { <global variables> } allow { <permission> }

Importing a module is like executing a script with the passed globals and granted permissions.

# content of https://example.com/return_1.gos
return 1

Script:

image

Routines

Routines are mainly used for concurrent work and isolation. Each routine has its own goroutine and state.

Embedded module:

image

Call syntax (all permissions are inherited).

routine = sr nil f()

Routines can optionally be part of a "routine group" that allows easier control of multiple routines. The group variable is defined (and updated) when the spawn expression is evaluated.

for (1 .. 10) {
    sr req_group nil read(https://debloat.dev/fakeapp/users)!
}

results = $req_group.WaitAllResults()!

For more details about the different features you can read the repository's wiki.

Implementation

  • Why use a tree walk interpreter instead of a bytecode interpreter ?
    -> Tree walk interpreters are slower but simpler : that means less bugs and vulnerabilities. A Gopherscript implementation that uses a bytecode interpreter might be developed in the future though.

Executables

When something tries to do too many things it becomes impossible to understand for the average developper. That makes audits and customization harder. Goperscript aims to have a different model. Depending on the features you need, you install one one more executables that try to do one thing well without uncessary bloat (each one providing specific globals to Gophercript).

Documentation

Index

Constants

View Source
const COMPUTE_TIME_TOTAL_LIMIT_NAME = "execution/total-compute-time"
View Source
const DEFAULT_MAX_STACK_HEIGHT = 5
View Source
const EXECUTION_TOTAL_LIMIT_NAME = "execution/total-time"
View Source
const GOPHERSCRIPT_MIMETYPE = "application/gopherscript"
View Source
const HTTP_URL_PATTERN = "^https?:\\/\\/(localhost|(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,32}\\.[a-zA-Z0-9]{1,6})\\b([-a-zA-Z0-9@:%_+.~#?&//=]{0,100})$"
View Source
const IMPLICIT_KEY_LEN_KEY = "__len"
View Source
const IO_TIME_TOTAL_LIMIT_NAME = "execution/total-io-time"
View Source
const LOOSE_HTTP_HOST_PATTERN_PATTERN = "^https?:\\/\\/(\\*|(www\\.)?[-a-zA-Z0-9.*]{1,32}\\.[a-zA-Z0-9*]{1,6})(:[0-9]{1,5})?$"
View Source
const LOOSE_URL_EXPR_PATTERN = "" /* 138-byte string literal not displayed */
View Source
const MAX_OBJECT_KEY_BYTE_LEN = 64
View Source
const MAX_PATTERN_OCCURRENCE_COUNT = 1 << 24
View Source
const RETURN_1_MODULE_HASH = "SG2a/7YNuwBjsD2OI6bM9jZM4gPcOp9W8g51DrQeyt4="
View Source
const RETURN_GLOBAL_A_MODULE_HASH = "UYvV2gLwfuQ2D91v7PzQ8RMugUTcM0lOysCMqMqXfmg"
View Source
const TOKEN_BUCKET_CAPACITY_SCALE = 100
View Source
const TOKEN_BUCKET_INTERVAL = time.Second / TOKEN_BUCKET_CAPACITY_SCALE
View Source
const TRULY_MAX_STACK_HEIGHT = 10

Variables

View Source
var BINARY_OPERATOR_STRINGS = []string{
	"+", "+.", "-", "-.", "*", "*.", "/", "/.", "++", "<", "<.", "<=", "<=", ">", ">.", ">=", ">=.", "==", "!=",
	"in", "not-in", "keyof", ".", "..", "..<", "and", "or", "match", "not-match", "Substrof",
}
View Source
var CONST_KEYWORD_STR = "const"
View Source
var CTX_PTR_TYPE = reflect.TypeOf(&Context{})
View Source
var ERROR_INTERFACE_TYPE = reflect.TypeOf((*error)(nil)).Elem()
View Source
var ITERABLE_INTERFACE_TYPE = reflect.TypeOf((*Iterable)(nil)).Elem()
View Source
var KEYWORDS = []string{"if", "else", "require", "drop-perms", "for", "assign", "const", "fn", "switch", "match", "import", "sr", "return", "break", "continue"}
View Source
var LOOSE_HTTP_HOST_PATTERN_REGEX = regexp.MustCompile(LOOSE_HTTP_HOST_PATTERN_PATTERN)
View Source
var LOOSE_URL_EXPR_PATTERN_REGEX = regexp.MustCompile(LOOSE_URL_EXPR_PATTERN)
View Source
var MODULE_CACHE = map[string]string{
	RETURN_1_MODULE_HASH:        "return 1",
	RETURN_GLOBAL_A_MODULE_HASH: "return $$a",
}
View Source
var PERMISSION_KIND_STRINGS = []string{"read", "update", "create", "delete", "use", "consume", "provide"}
View Source
var REQUIRE_KEYWORD_STR = "require"
View Source
var UINT8_SLICE_TYPE = reflect.TypeOf(([]uint8)(nil)).Elem()

Functions

func CallFunc

func CallFunc(calleeNode Node, state *State, arguments interface{}, must bool) (interface{}, error)

CallFunc calls calleeNode, whatever its kind (Gopherscript function or Go function). If must is true and the second result of a Go function is a non-nil error, CallFunc will panic.

func Check

func Check(node Node) error

Check performs various checks on an AST, like checking that return, break and continue statements are not misplaced. Some checks are done while parsing : see the ParseModule function.

func Eval

func Eval(node Node, state *State) (result interface{}, err error)

Evaluates a node, panics are always recovered so this function should not panic.

func ExtValOf

func ExtValOf(v interface{}, state *State) interface{}

func HasPathLikeStart added in v0.5.0

func HasPathLikeStart(s string) bool

func IsGopherVal added in v0.3.5

func IsGopherVal(v interface{}) bool

func IsSimpleGopherVal added in v0.1.2

func IsSimpleGopherVal(v interface{}) bool

func IsSimpleValueLiteral added in v0.6.0

func IsSimpleValueLiteral(node Node) bool

func Memb added in v0.5.0

func Memb(value interface{}, name string) (interface{}, *reflect.Type, error)

func MustEval

func MustEval(node Node, state *State) interface{}

MustEval calls Eval and panics if there is an error.

func ToReflectVal

func ToReflectVal(v interface{}) reflect.Value

Wraps its argument in a reflect.Value if it is not already wrapped.

func Traverse

func Traverse(v interface{}, fn func(interface{}) (TraversalAction, error), config TraversalConfiguration) (terror error)

Traverse a graph of values starting from v. Only objects & lists are considered source nodes, the other ones are sinks (leafs). A list of encountered source nodes is used to prevent cycling

func UnwrapReflectVal

func UnwrapReflectVal(v interface{}) interface{}

Unwraps the content of a reflect.Value.

func ValOf

func ValOf(v interface{}) interface{}

Unwraps any reflect.Value that wraps a Gopherscript value. Wraps its argument in a reflect.Value if it is not a Gopherscript value.

func Walk

func Walk(node Node, fn func(Node, Node, Node, []Node) (error, TraversalAction)) (err error)

This functions performs a pre-order traversal on an AST (depth first).

Types

type AbsolutePathExpression

type AbsolutePathExpression struct {
	NodeBase
	Slices []Node
}

type AbsolutePathLiteral

type AbsolutePathLiteral struct {
	NodeBase
	Value string
}

type AbsolutePathPatternLiteral

type AbsolutePathPatternLiteral struct {
	NodeBase
	Value string
}

type Assignment

type Assignment struct {
	NodeBase
	Left  Node
	Right Node
}

type AtHostLiteral added in v0.5.0

type AtHostLiteral struct {
	NodeBase
	Value string
}

type BinaryExpression

type BinaryExpression struct {
	NodeBase
	Operator BinaryOperator
	Left     Node
	Right    Node
}

type BinaryOperator

type BinaryOperator int
const (
	Add BinaryOperator = iota
	AddF
	Sub
	SubF
	Mul
	MulF
	Div
	DivF
	Concat
	LessThan
	LessThanF
	LessOrEqual
	LessOrEqualF
	GreaterThan
	GreaterThanF
	GreaterOrEqual
	GreaterOrEqualF
	Equal
	NotEqual
	In
	NotIn
	Keyof
	Dot //unused, present for symmetry
	Range
	ExclEndRange
	And
	Or
	Match
	NotMatch
	Substrof
)

func (BinaryOperator) String

func (operator BinaryOperator) String() string

type Block

type Block struct {
	NodeBase
	Statements []Node
}

type BooleanConversionExpression added in v0.5.0

type BooleanConversionExpression struct {
	NodeBase
	Expr Node
}

type BooleanLiteral

type BooleanLiteral struct {
	NodeBase
	Value bool
}

type BreakStatement added in v0.3.0

type BreakStatement struct {
	NodeBase
	Label *IdentifierLiteral //can be nil
}

type ByteCount added in v0.2.0

type ByteCount int

type ByteRate added in v0.2.0

type ByteRate int

type Call

type Call struct {
	NodeBase
	Callee    Node
	Arguments []Node
	Must      bool
}

type Case

type Case struct {
	NodeBase
	Value Node
	Block *Block
}

type CommandPermission added in v0.1.2

type CommandPermission struct {
	CommandName         string
	SubcommandNameChain []string //can be empty
}

func (CommandPermission) Includes added in v0.1.2

func (perm CommandPermission) Includes(otherPerm Permission) bool

func (CommandPermission) Kind added in v0.1.2

func (perm CommandPermission) Kind() PermissionKind

func (CommandPermission) String added in v0.1.2

func (perm CommandPermission) String() string

type Context

type Context struct {
	// contains filtered or unexported fields
}

func NewContext

func NewContext(permissions []Permission, forbiddenPermissions []Permission, limitations []Limitation) *Context

func (*Context) CheckHasPermission

func (ctx *Context) CheckHasPermission(perm Permission) error

func (*Context) DropPermissions added in v0.5.0

func (ctx *Context) DropPermissions(droppedPermissions []Permission)

func (*Context) GetRate added in v0.2.0

func (ctx *Context) GetRate(name string) (ByteRate, error)

func (*Context) HasPermission

func (ctx *Context) HasPermission(perm Permission) bool

func (*Context) NewWith added in v0.3.1

func (ctx *Context) NewWith(additionalPerms []Permission) (*Context, error)

Creates a new Context with additional permissions

func (*Context) NewWithout added in v0.3.1

func (ctx *Context) NewWithout(removedPerms []Permission) (*Context, error)

Creates a new Context with the permissions passed as argument removed. The limiters are shared between the two contexts.

func (*Context) Take added in v0.2.0

func (ctx *Context) Take(name string, count int64)

type ContextlessCallPermission added in v0.3.1

type ContextlessCallPermission struct {
	FuncMethodName   string
	ReceiverTypeName string
}

func (ContextlessCallPermission) Includes added in v0.3.1

func (perm ContextlessCallPermission) Includes(otherPerm Permission) bool

func (ContextlessCallPermission) Kind added in v0.3.1

func (ContextlessCallPermission) String added in v0.3.1

func (perm ContextlessCallPermission) String() string

type ContinueStatement added in v0.3.0

type ContinueStatement struct {
	NodeBase
	Label *IdentifierLiteral //can be nil
}

type EmbeddedModule

type EmbeddedModule struct {
	NodeBase
	Requirements *Requirements
	Statements   []Node
}

type EntryMatcher added in v0.5.0

type EntryMatcher struct {
	Key   Matcher
	Value Matcher
}

type ExactSimpleValueMatcher added in v0.5.0

type ExactSimpleValueMatcher struct {
	// contains filtered or unexported fields
}

func (ExactSimpleValueMatcher) Random added in v0.5.0

func (matcher ExactSimpleValueMatcher) Random() interface{}

func (ExactSimpleValueMatcher) Regex added in v0.5.0

func (matcher ExactSimpleValueMatcher) Regex() string

func (ExactSimpleValueMatcher) Test added in v0.5.0

func (matcher ExactSimpleValueMatcher) Test(v interface{}) bool

type ExternalValue

type ExternalValue struct {
	// contains filtered or unexported fields
}

type ExtractionExpression added in v0.5.0

type ExtractionExpression struct {
	NodeBase
	Object Node
	Keys   *KeyListExpression
}

type FilesystemPermission

type FilesystemPermission struct {
	Kind_  PermissionKind
	Entity interface{} //Path, PathPattern ...
}

func (FilesystemPermission) Includes

func (perm FilesystemPermission) Includes(otherPerm Permission) bool

func (FilesystemPermission) Kind

func (FilesystemPermission) String

func (perm FilesystemPermission) String() string

type FloatLiteral

type FloatLiteral struct {
	NodeBase
	Raw   string
	Value float64
}

type ForStatement

type ForStatement struct {
	NodeBase
	KeyIndexIdent  *IdentifierLiteral //can be nil
	ValueElemIdent *IdentifierLiteral //can be nil
	Body           *Block
	IteratedValue  Node
}

type Func

type Func Node

type FunctionDeclaration

type FunctionDeclaration struct {
	NodeBase
	Function *FunctionExpression
	Name     *IdentifierLiteral
}

type FunctionExpression

type FunctionExpression struct {
	NodeBase
	Parameters   []*FunctionParameter
	Body         *Block
	Requirements *Requirements
}

type FunctionParameter

type FunctionParameter struct {
	NodeBase
	Var *IdentifierLiteral
}

type GenerativePattern added in v0.5.0

type GenerativePattern interface {
	Random() interface{}
}

todo: improve name

type GlobalConstantDeclaration added in v0.5.0

type GlobalConstantDeclaration struct {
	NodeBase
	Left  *IdentifierLiteral
	Right Node
}

type GlobalConstantDeclarations

type GlobalConstantDeclarations struct {
	NodeBase
	Declarations []*GlobalConstantDeclaration
}

type GlobalVarPermission

type GlobalVarPermission struct {
	Kind_ PermissionKind
	Name  string //"*" means any
}

func (GlobalVarPermission) Includes

func (perm GlobalVarPermission) Includes(otherPerm Permission) bool

func (GlobalVarPermission) Kind

func (perm GlobalVarPermission) Kind() PermissionKind

func (GlobalVarPermission) String

func (perm GlobalVarPermission) String() string

type GlobalVariable

type GlobalVariable struct {
	NodeBase
	Name string
}

type GroupMatcher added in v0.5.0

type GroupMatcher interface {
	Matcher
	MatchGroups(interface{}) (ok bool, groups map[string]interface{})
}

type HTTPHost

type HTTPHost string

type HTTPHostLiteral

type HTTPHostLiteral struct {
	NodeBase
	Value string
}

type HTTPHostPattern

type HTTPHostPattern string

func (HTTPHostPattern) Test added in v0.3.5

func (patt HTTPHostPattern) Test(v interface{}) bool

type HTTPHostPatternLiteral

type HTTPHostPatternLiteral struct {
	NodeBase
	Value string
}

type HostAliasDefinition added in v0.5.0

type HostAliasDefinition struct {
	NodeBase
	Left  *AtHostLiteral
	Right Node
}

type HttpPermission

type HttpPermission struct {
	Kind_  PermissionKind
	Entity interface{} //URL, URLPattern, HTTPHost, HTTPHostPattern ....
}

func (HttpPermission) Includes

func (perm HttpPermission) Includes(otherPerm Permission) bool

func (HttpPermission) Kind

func (perm HttpPermission) Kind() PermissionKind

func (HttpPermission) String

func (perm HttpPermission) String() string

type Identifier

type Identifier string

type IdentifierLiteral

type IdentifierLiteral struct {
	NodeBase
	Name string
}

type IdentifierMemberExpression

type IdentifierMemberExpression struct {
	NodeBase
	Left          *IdentifierLiteral
	PropertyNames []*IdentifierLiteral
}

type IfStatement

type IfStatement struct {
	NodeBase
	Test       Node
	Consequent *Block
	Alternate  *Block //can be nil
}

type ImportStatement

type ImportStatement struct {
	NodeBase
	Identifier         *IdentifierLiteral
	URL                *URLLiteral
	ValidationString   *StringLiteral
	ArgumentObject     *ObjectLiteral
	GrantedPermissions *ObjectLiteral
}

type IndexExpression

type IndexExpression struct {
	NodeBase
	Indexed Node
	Index   Node
}

type IntLiteral

type IntLiteral struct {
	NodeBase
	Raw   string
	Value int
}

type IntRange

type IntRange struct {
	Start int
	End   int
	Step  int
	// contains filtered or unexported fields
}

func (IntRange) Iterator

func (r IntRange) Iterator() Iterator

func (IntRange) Random added in v0.5.0

func (r IntRange) Random() interface{}

type IntRangeIterator

type IntRangeIterator struct {
	// contains filtered or unexported fields
}

func (*IntRangeIterator) GetNext

func (it *IntRangeIterator) GetNext(ctx *Context) interface{}

func (IntRangeIterator) HasNext

func (it IntRangeIterator) HasNext(*Context) bool

type IntegerRangeLiteral added in v0.5.0

type IntegerRangeLiteral struct {
	NodeBase
	LowerBound *IntLiteral
	UpperBound *IntLiteral
}

type InvalidAliasRelatedNode added in v0.5.0

type InvalidAliasRelatedNode struct {
	NodeBase
	Value string
}

type InvalidComplexPatternElement added in v0.5.0

type InvalidComplexPatternElement struct {
	NodeBase
}

type InvalidMemberLike added in v0.5.0

type InvalidMemberLike struct {
	NodeBase
	Left  Node
	Right Node //can be nil
}

type InvalidObjectElement added in v0.5.0

type InvalidObjectElement struct {
	NodeBase
}

type InvalidURL added in v0.5.0

type InvalidURL struct {
	NodeBase
	Value string
}

type InvalidURLPattern added in v0.5.0

type InvalidURLPattern struct {
	NodeBase
	Value string
}

type Iterable

type Iterable interface {
	Iterator() Iterator
}

type IterationChange added in v0.3.0

type IterationChange int
const (
	NoIterationChange IterationChange = iota
	BreakIteration
	ContinueIteration
)

type Iterator

type Iterator interface {
	HasNext(*Context) bool
	GetNext(*Context) interface{}
}

type JSONstring

type JSONstring string

special string types

type KeyList

type KeyList []string

type KeyListExpression

type KeyListExpression struct {
	NodeBase
	Keys []*IdentifierLiteral
}

type LazyExpression

type LazyExpression struct {
	NodeBase
	Expression Node
}

type Limitation added in v0.2.0

type Limitation struct {
	Name        string
	SimpleRate  SimpleRate
	ByteRate    ByteRate
	Total       int64
	DecrementFn func(time.Time) int64
}

type Limiter added in v0.2.0

type Limiter struct {
	// contains filtered or unexported fields
}

type LineCount

type LineCount int

type List

type List []interface{}

func (List) ContainsSimple added in v0.3.6

func (list List) ContainsSimple(v interface{}) bool

type ListLiteral

type ListLiteral struct {
	NodeBase
	Elements []Node
}

type ListPattern added in v0.5.0

type ListPattern struct {
	ElementMatchers []Matcher
}

func (ListPattern) Test added in v0.5.0

func (patt ListPattern) Test(v interface{}) bool

type ListPatternLiteral added in v0.5.0

type ListPatternLiteral struct {
	NodeBase
	Elements []Node
}

type LoadType added in v0.4.0

type LoadType int
const (
	ComputeLoad LoadType = iota
	IOLoad
)

type MatchStatement

type MatchStatement struct {
	NodeBase
	Discriminant Node
	Cases        []*Case
}

type Matcher

type Matcher interface {
	Test(interface{}) bool
}

func CompilePatternNode added in v0.5.0

func CompilePatternNode(node Node, state *State) (Matcher, error)

type MemberExpression

type MemberExpression struct {
	NodeBase
	Left         Node
	PropertyName *IdentifierLiteral
}

type MissingExpression added in v0.6.0

type MissingExpression struct {
	NodeBase
}

type Module

type Module struct {
	NodeBase
	GlobalConstantDeclarations *GlobalConstantDeclarations //nil if no const declarations at the top of the module
	Requirements               *Requirements               //nil if no require at the top of the module
	Statements                 []Node
}

func MustParseModule

func MustParseModule(str string) (result *Module)

func ParseAndCheckModule

func ParseAndCheckModule(s string, fpath string) (*Module, error)

func ParseModule

func ParseModule(str string, fpath string) (result *Module, resultErr error)

parses a file module, resultErr is either a non-sntax error or an aggregation of syntax errors. result and resultErr can be both non-nil at the same time because syntax errors are also stored in each node.

type MultiAssignment

type MultiAssignment struct {
	NodeBase
	Variables []Node
	Right     Node
}

type NamedSegmentPathPattern added in v0.5.0

type NamedSegmentPathPattern struct {
	// contains filtered or unexported fields
}

func (NamedSegmentPathPattern) MatchGroups added in v0.5.0

func (patt NamedSegmentPathPattern) MatchGroups(v interface{}) (bool, map[string]interface{})

func (NamedSegmentPathPattern) Test added in v0.5.0

func (patt NamedSegmentPathPattern) Test(v interface{}) bool

type NamedSegmentPathPatternLiteral added in v0.5.0

type NamedSegmentPathPatternLiteral struct {
	NodeBase
	Slices []Node //PathSlice | Variable
}

TODO: rename

type NilLiteral

type NilLiteral struct {
	NodeBase
}

type Node

type Node interface {
	Base() NodeBase
}

all node types embed NodeBase, NodeBase implements the Node interface

type NodeBase

type NodeBase struct {
	Span            NodeSpan
	Err             *ParsingError
	ValuelessTokens []ValuelessToken
}

func (NodeBase) Base

func (base NodeBase) Base() NodeBase

func (NodeBase) IncludedIn added in v0.2.0

func (base NodeBase) IncludedIn(node Node) bool

type NodeCategory added in v0.2.0

type NodeCategory int
const (
	UnspecifiedCategory NodeCategory = iota
	URLlike
	Pathlike
	IdentLike
	KnownType
)

type NodeSpan

type NodeSpan struct {
	Start int
	End   int
}

type NotAllowedError

type NotAllowedError struct {
	Permission Permission
	Message    string
}

func (NotAllowedError) Error

func (err NotAllowedError) Error() string

type Object

type Object map[string]interface{}

int, float64, string, bool, reflect.Value

func (Object) GetOrDefault added in v0.3.6

func (obj Object) GetOrDefault(key string, defaultVal interface{}) interface{}

type ObjectLiteral

type ObjectLiteral struct {
	NodeBase
	Properties     []ObjectProperty
	SpreadElements []*PropertySpreadElement
}

func (ObjectLiteral) PermissionsLimitations added in v0.2.0

func (objLit ObjectLiteral) PermissionsLimitations(
	globalConsts *GlobalConstantDeclarations,
	runningState *State,
	handleCustomType func(kind PermissionKind, name string, value Node) (perms []Permission, handled bool, err error),
) ([]Permission, []Limitation)

this function get permissions limitations & by evaluating a "requirement" object literal custom permissions & most limitations are handled by the handleCustomType argument (optional)

type ObjectPattern added in v0.5.0

type ObjectPattern struct {
	EntryMatchers map[string]Matcher
}

func (ObjectPattern) Test added in v0.5.0

func (patt ObjectPattern) Test(v interface{}) bool

type ObjectPatternLiteral added in v0.5.0

type ObjectPatternLiteral struct {
	NodeBase
	Properties []ObjectProperty
}

type ObjectProperty

type ObjectProperty struct {
	NodeBase
	Key   Node //can be nil (implicit key)
	Value Node
}

func (ObjectProperty) HasImplicitKey added in v0.1.2

func (prop ObjectProperty) HasImplicitKey() bool

func (ObjectProperty) Name

func (prop ObjectProperty) Name() string

type OcurrenceCountModifier added in v0.5.0

type OcurrenceCountModifier int
const (
	ExactlyOneOcurrence OcurrenceCountModifier = iota
	AtLeastOneOcurrence
	ZeroOrMoreOcurrence
	OptionalOcurrence
	ExactOcurrence
)

type ParsingError

type ParsingError struct {
	Message string
	Index   int

	NodeStartIndex int //< 0 if not specified
	NodeCategory   NodeCategory
	NodeType       Node //not nil if .NodeCategory is KnownType
}

func (ParsingError) Error

func (err ParsingError) Error() string

type Path

type Path string

func (Path) IsDirPath

func (pth Path) IsDirPath() bool

func (Path) ToAbs

func (pth Path) ToAbs() Path

type PathPattern

type PathPattern string

func (PathPattern) IsPrefixPattern

func (patt PathPattern) IsPrefixPattern() bool

func (PathPattern) Prefix

func (patt PathPattern) Prefix() string

func (PathPattern) Test added in v0.3.5

func (patt PathPattern) Test(v interface{}) bool

func (PathPattern) ToAbs

func (patt PathPattern) ToAbs() PathPattern

type PathSlice

type PathSlice struct {
	NodeBase
	Value string
}

type PatternDefinition added in v0.5.0

type PatternDefinition struct {
	NodeBase
	Left  *PatternIdentifierLiteral
	Right Node
}

type PatternIdentifierLiteral added in v0.5.0

type PatternIdentifierLiteral struct {
	NodeBase
	Name string
}

type PatternKind added in v0.5.0

type PatternKind int
const (
	UnspecifiedPatternKind PatternKind = iota
	StringPattern
	IntegerPattern
	FloatPattern
)

type PatternPiece added in v0.5.0

type PatternPiece struct {
	NodeBase
	Kind     PatternKind
	Elements []*PatternPieceElement
}

type PatternPieceElement added in v0.5.0

type PatternPieceElement struct {
	NodeBase
	Ocurrence           OcurrenceCountModifier
	ExactOcurrenceCount int
	Expr                Node
}

type PatternUnion added in v0.5.0

type PatternUnion struct {
	NodeBase
	Cases []Node
}

type Permission

type Permission interface {
	Kind() PermissionKind
	Includes(Permission) bool
	String() string
}

type PermissionDroppingStatement added in v0.5.0

type PermissionDroppingStatement struct {
	NodeBase
	Object *ObjectLiteral
}

type PermissionKind

type PermissionKind int
const (
	ReadPerm PermissionKind = iota
	UpdatePerm
	CreatePerm
	DeletePerm
	UsePerm
	ConsumePerm
	ProvidePerm
)

func PermissionKindFromString

func PermissionKindFromString(s string) (PermissionKind, bool)

func (PermissionKind) String

func (kind PermissionKind) String() string

type PipelineExpression added in v0.5.0

type PipelineExpression struct {
	NodeBase
	Stages []*PipelineStage
}

type PipelineStage added in v0.5.0

type PipelineStage struct {
	Kind PipelineStageKind
	Expr Node
}

type PipelineStageKind added in v0.5.0

type PipelineStageKind int
const (
	NormalStage PipelineStageKind = iota
	ParallelStage
)

type PipelineStatement added in v0.5.0

type PipelineStatement struct {
	NodeBase
	Stages []*PipelineStage
}

type PropertySpreadElement added in v0.5.0

type PropertySpreadElement struct {
	NodeBase
	Extraction *ExtractionExpression
}

type QuantityLiteral

type QuantityLiteral struct {
	NodeBase
	Raw   string
	Value float64
	Unit  string
}

type QuantityRange

type QuantityRange struct {
	Start interface{}
	End   interface{}
	// contains filtered or unexported fields
}

type RateLiteral added in v0.2.0

type RateLiteral struct {
	NodeBase
	Quantity *QuantityLiteral
	Unit     *IdentifierLiteral
}

type RegexMatcher added in v0.5.0

type RegexMatcher struct {
	// contains filtered or unexported fields
}

func (RegexMatcher) Regex added in v0.5.0

func (matcher RegexMatcher) Regex() string

func (RegexMatcher) Test added in v0.5.0

func (matcher RegexMatcher) Test(v interface{}) bool

type RegularExpressionLiteral added in v0.5.0

type RegularExpressionLiteral struct {
	NodeBase
	Raw   string
	Value string
}

type RelativePathExpression

type RelativePathExpression struct {
	NodeBase
	Slices []Node
}

type RelativePathLiteral

type RelativePathLiteral struct {
	NodeBase
	Value string
}

type RelativePathPatternLiteral

type RelativePathPatternLiteral struct {
	NodeBase
	Value string
}

type RepeatedPatternElement added in v0.5.0

type RepeatedPatternElement struct {
	// contains filtered or unexported fields
}

func (RepeatedPatternElement) Random added in v0.5.0

func (patt RepeatedPatternElement) Random() interface{}

func (RepeatedPatternElement) Regex added in v0.5.0

func (patt RepeatedPatternElement) Regex() string

func (RepeatedPatternElement) Test added in v0.5.0

func (patt RepeatedPatternElement) Test(v interface{}) bool

type Requirements

type Requirements struct {
	ValuelessTokens []ValuelessToken
	Object          *ObjectLiteral
}

type ReturnStatement

type ReturnStatement struct {
	NodeBase
	Expr Node
}

type Routine

type Routine struct {
	// contains filtered or unexported fields
}

func (*Routine) WaitResult

func (routine *Routine) WaitResult(ctx *Context) (interface{}, error)

type RoutineGroup

type RoutineGroup struct {
	// contains filtered or unexported fields
}

func (*RoutineGroup) WaitAllResults

func (group *RoutineGroup) WaitAllResults(ctx *Context) (interface{}, error)

type RoutinePermission

type RoutinePermission struct {
	Kind_ PermissionKind
}

func (RoutinePermission) Includes

func (perm RoutinePermission) Includes(otherPerm Permission) bool

func (RoutinePermission) Kind

func (perm RoutinePermission) Kind() PermissionKind

func (RoutinePermission) String

func (perm RoutinePermission) String() string

type RuneLiteral added in v0.5.0

type RuneLiteral struct {
	NodeBase
	Value rune
}

type RuneRange added in v0.5.0

type RuneRange struct {
	Start rune
	End   rune
}

TODO: implement Iterable

func (RuneRange) Random added in v0.5.0

func (r RuneRange) Random() interface{}

func (RuneRange) RandomRune added in v0.5.0

func (r RuneRange) RandomRune() rune

type RuneRangeExpression added in v0.5.0

type RuneRangeExpression struct {
	NodeBase
	Lower *RuneLiteral
	Upper *RuneLiteral
}

type RuneRangeStringPattern added in v0.5.0

type RuneRangeStringPattern struct {
	// contains filtered or unexported fields
}

func (RuneRangeStringPattern) Random added in v0.5.0

func (patt RuneRangeStringPattern) Random() interface{}

func (RuneRangeStringPattern) Regex added in v0.5.0

func (patt RuneRangeStringPattern) Regex() string

func (RuneRangeStringPattern) Test added in v0.5.0

func (patt RuneRangeStringPattern) Test(v interface{}) bool

type SequenceStringPattern added in v0.5.0

type SequenceStringPattern struct {
	// contains filtered or unexported fields
}

func (SequenceStringPattern) Random added in v0.5.0

func (patt SequenceStringPattern) Random() interface{}

func (SequenceStringPattern) Regex added in v0.5.0

func (patt SequenceStringPattern) Regex() string

func (SequenceStringPattern) Test added in v0.5.0

func (patt SequenceStringPattern) Test(v interface{}) bool

type SimpleRate added in v0.4.0

type SimpleRate int

type SliceExpression

type SliceExpression struct {
	NodeBase
	Indexed    Node
	StartIndex Node //can be nil
	EndIndex   Node //can be nil
}

type SpawnExpression

type SpawnExpression struct {
	NodeBase
	GroupIdent         *IdentifierLiteral //can be nil
	Globals            Node
	ExprOrVar          Node
	GrantedPermissions *ObjectLiteral //nil if no "allow ...." in the spawn expression
}

type StackPermission

type StackPermission struct {
	// contains filtered or unexported fields
}

func (StackPermission) Includes

func (perm StackPermission) Includes(otherPerm Permission) bool

func (StackPermission) Kind

func (perm StackPermission) Kind() PermissionKind

func (StackPermission) String

func (perm StackPermission) String() string

type State

type State struct {
	ScopeStack  []map[string]interface{}
	ReturnValue *interface{}
	IterationChange

	Script     []rune
	ScriptName string
	// contains filtered or unexported fields
}

func NewState

func NewState(ctx *Context, args ...map[string]interface{}) *State

func (State) CurrentScope

func (state State) CurrentScope() map[string]interface{}

func (State) GlobalScope

func (state State) GlobalScope() map[string]interface{}

func (*State) PopScope

func (state *State) PopScope()

func (*State) PushScope

func (state *State) PushScope()

type Statement

type Statement interface {
	Node
}

type StringLiteral

type StringLiteral struct {
	NodeBase
	Raw   string
	Value string
}

type StringPatternElement added in v0.5.0

type StringPatternElement interface {
	Matcher
	GenerativePattern
	Regex() string
}

func CompileStringPatternNode added in v0.5.0

func CompileStringPatternNode(node Node, state *State) (StringPatternElement, error)

type SwitchStatement

type SwitchStatement struct {
	NodeBase
	Discriminant Node
	Cases        []*Case
}

type TokenBucket added in v0.2.0

type TokenBucket struct {
	// contains filtered or unexported fields
}

TokenBucket represents a token bucket (https://en.wikipedia.org/wiki/Token_bucket) which based on multi goroutines, and is safe to use under concurrency environments.

func (*TokenBucket) Availible added in v0.2.0

func (tb *TokenBucket) Availible() int64

Availible returns how many tokens are availible in the bucket.

func (*TokenBucket) Capability added in v0.2.0

func (tb *TokenBucket) Capability() int64

Capability returns the capability of this token bucket.

func (*TokenBucket) Destroy added in v0.4.0

func (tb *TokenBucket) Destroy()

Destroy destroys the token bucket and stop the inner channels.

func (*TokenBucket) Take added in v0.2.0

func (tb *TokenBucket) Take(count int64)

Take tasks specified count tokens from the bucket, if there are not enough tokens in the bucket, it will keep waiting until count tokens are availible and then take them.

func (*TokenBucket) TakeMaxDuration added in v0.2.0

func (tb *TokenBucket) TakeMaxDuration(count int64, max time.Duration) bool

TakeMaxDuration tasks specified count tokens from the bucket, if there are not enough tokens in the bucket, it will keep waiting until count tokens are availible and then take them or just return false when reach the given max duration.

func (*TokenBucket) TryTake added in v0.2.0

func (tb *TokenBucket) TryTake(count int64) bool

TryTake trys to task specified count tokens from the bucket. if there are not enough tokens in the bucket, it will return false.

func (*TokenBucket) Wait added in v0.2.0

func (tb *TokenBucket) Wait(count int64)

Wait will keep waiting until count tokens are availible in the bucket.

func (*TokenBucket) WaitMaxDuration added in v0.2.0

func (tb *TokenBucket) WaitMaxDuration(count int64, max time.Duration) bool

WaitMaxDuration will keep waiting until count tokens are availible in the bucket or just return false when reach the given max duration.

type TraversalAction

type TraversalAction int
const (
	Continue TraversalAction = iota
	Prune
	StopTraversal
)

type TraversalConfiguration

type TraversalConfiguration struct {
	MaxDepth int
}

type TraversalOrder

type TraversalOrder int

type URL

type URL string

type URLExpression

type URLExpression struct {
	NodeBase
	Raw         string
	HostPart    Node
	Path        *AbsolutePathExpression
	QueryParams []Node
}

type URLLiteral

type URLLiteral struct {
	NodeBase
	Value string
}

type URLPattern

type URLPattern string

func (URLPattern) Prefix

func (patt URLPattern) Prefix() string

func (URLPattern) Test added in v0.3.5

func (patt URLPattern) Test(v interface{}) bool

type URLPatternLiteral

type URLPatternLiteral struct {
	NodeBase
	Value string
}

type URLQueryExpression added in v0.3.6

type URLQueryExpression struct {
	NodeBase
	Parameters map[string][]Node
}

type URLQueryParameter added in v0.3.6

type URLQueryParameter struct {
	NodeBase
	Name  string
	Value []Node
}

type URLQueryParameterSlice added in v0.3.6

type URLQueryParameterSlice struct {
	NodeBase
	Value string
}

type UnionStringPattern added in v0.5.0

type UnionStringPattern struct {
	// contains filtered or unexported fields
}

func (UnionStringPattern) Random added in v0.5.0

func (patt UnionStringPattern) Random() interface{}

func (UnionStringPattern) Regex added in v0.5.0

func (patt UnionStringPattern) Regex() string

func (UnionStringPattern) Test added in v0.5.0

func (patt UnionStringPattern) Test(v interface{}) bool

type UnknownNode added in v0.5.0

type UnknownNode struct {
	NodeBase
}

type UpperBoundRangeExpression

type UpperBoundRangeExpression struct {
	NodeBase
	UpperBound Node
}

type ValuelessToken added in v0.6.0

type ValuelessToken struct {
	Type ValuelessTokenType
	Span NodeSpan
}

type ValuelessTokenType added in v0.6.0

type ValuelessTokenType int
const (
	IF_KEYWORD ValuelessTokenType = iota
	ELSE_KEYWORD
	REQUIRE_KEYWORD
	DROP_PERMS_KEYWORD
	ASSIGN_KEYWORD
	CONST_KEYWORD
	FOR_KEYWORD
	IN_KEYWORD
	SPAWN_KEYWORD
	ALLOW_KEYWORD
	IMPORT_KEYWORD
	FN_KEYWORD
	SWITCH_KEYWORD
	MATCH_KEYWORD
	RETURN_KEYWORD
	BREAK_KEYWORD
	CONTINUE_KEYWORD
	OPENING_BRACKET
	CLOSING_BRACKET
	OPENING_CURLY_BRACKET
	CLOSING_CURLY_BRACKET
	OPENING_PARENTHESIS
	CLOSING_PARENTHESIS
	COMMA
	COLON
	SEMICOLON
)

type Variable

type Variable struct {
	NodeBase
	Name string
}

Directories

Path Synopsis
cmd
gos

Jump to

Keyboard shortcuts

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