value

package
v0.5.8 Latest Latest
Warning

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

Go to latest
Published: May 23, 2026 License: BSD-3-Clause Imports: 24 Imported by: 19

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BinaryOps = make(map[string]BinaryOp)
View Source
var IvyEval func(context Context, s string) Value

Implemented in package run, handled as a func to avoid a dependency loop.

View Source
var (
	MaxBigInt63 = big.NewInt(int64(^uint64(0) >> 1)) // Used in ../parse/special.go

)
View Source
var (
	// The parameters for generating coefficients for our gamma apprximation. See
	// [The Gamma Function via Interpolation by Matthew F. Causley]: https://arxiv.org/pdf/2104.00697v1
	// The method is a refinement of Spouge's (1994) approximation for the gamma
	// function. For most values, the technique allows us to create a
	// significantly more accurate approximation than Lanczos, which only gets
	// to about 12 digits. In some parts of the complex plane this code can get
	// above 50 digits of accuracy. See ../testdata/gamma for details. N is the
	// number of coefficients. r is chosen as optimizing for best fit at z=6.
	// That choice is arbitrary. 256 bits of mantissa suffice to hold these
	// constants, with room.
	N = 100
)
View Source
var UnaryOps = make(map[string]UnaryOp)

Functions

func Assign added in v0.3.8

func Assign(c Context, op string, left, right Expr, rhs Value)

func DebugProgString added in v0.5.0

func DebugProgString(p progStringer) string

DebugProgString builds a string representation of p, to be used in debugging and error messages. If the argument is a vector or matrix expression, it needs special handling to get parentheses and nesting; otherwise we could just call ProgString.

func FlushState added in v0.5.0

func FlushState(expr Expr)

FlushState flushes saved Statement parse information in the expression tree.

func IndexAssign added in v0.1.12

func IndexAssign(context Context, top, left Expr, lvarx *VarExpr, index []Expr, right Expr, rhs Value)

IndexAssign handles general assignment to indexed expressions on the LHS. Left and index will be evaluated (right to left), while top is only for DebugProgString. The caller must check that left is a variable expression and pass lvar, the variable corresponding to left.

func IsCompound added in v0.3.8

func IsCompound(x interface{}) bool

IsCompound reports whether the item is a non-trivial expression tree, one that may require parentheses around it when printed to maintain correct evaluation order.

func IsScalarType added in v0.3.0

func IsScalarType(c Context, v Value) bool

IsScalarType reports whether u is an actual scalar, an int or float etc.

func IvyPrint added in v0.5.0

func IvyPrint(c Context, out io.Writer, val Value, withParens bool)

IvyPrint writes to out a version of the value that will recreate it when parsed. Its output depends on the context, unlike that of DebugProgString.

func MaxParallelismForTesting added in v0.1.12

func MaxParallelismForTesting()

func OrderedCompare added in v0.3.0

func OrderedCompare(c Context, u, v Value) int

OrderedCompare returns -1, 0, or 1 according to whether u is less than, equal to, or greater than v, according to total ordering rules. Total ordering is not the usual mathematical definition, as we honor things like 1.0 == 1, comparison of int and char is forbidden, and complex numbers do not implement <. Plus other than for scalars we don't need to follow any particular rules at all, just what works for sorting sets.

Thus we amend the usual orderings: - Char is below all other types - All other scalars are compared directly, except... - ...Complex is above all other scalars, unless on the real line: 1j0 == 1. - Vector is above all other types except... - ...Matrix, which is above all other types.

When comparing identically-typed values:

  • Complex is ordered first by real component, then by imaginary.
  • Vector and Matrix are ordered first by number of elements, then in lexical order of elements.

These are unusual rules, but they are provide a unique ordering of elements sufficient for set membership. // Exported for testing, which is done by the parent directory to avoid a dependency cycle.

func ParseString

func ParseString(c Context, s string) (string, error)

ParseString parses a string. Single quotes and double quotes are both allowed (but must be consistent.) The result must contain only valid Unicode code points.

func SetDebugContext added in v0.4.2

func SetDebugContext(c Context)

func TraceBinary added in v0.3.10

func TraceBinary(c Context, level int, u Value, op string, v Value)

TraceBinary prints a trace line for a binary operator.

func TraceUnary added in v0.3.10

func TraceUnary(c Context, level int, op string, v Value)

TraceUnary prints a trace line for a unary operator.

Types

type BigFloat

type BigFloat struct {
	*big.Float
}

func Consts

func Consts(c Context) (e, pi BigFloat)

func (BigFloat) Eval

func (f BigFloat) Eval(Context) Value

func (BigFloat) Format

func (f BigFloat) Format()

The fmt package looks for Formatter before Stringer, but we want to use Stringer only. big.Float implements Formatter, and we embed it in our BigFloat type. To make sure that our String gets called rather than the inner Format, we put a non-matching stub Format method into this interface. This is ugly but very simple and cheap.

func (BigFloat) Inner

func (f BigFloat) Inner() Value

func (BigFloat) ProgString

func (f BigFloat) ProgString() string

func (BigFloat) Rank

func (f BigFloat) Rank() int

func (BigFloat) Sprint

func (f BigFloat) Sprint(c Context) string

func (BigFloat) String

func (f BigFloat) String() string

type BigInt

type BigInt struct {
	*big.Int
}

func (BigInt) BitLen

func (i BigInt) BitLen() int64

func (BigInt) Eval

func (i BigInt) Eval(Context) Value

func (BigInt) Format

func (i BigInt) Format()

The fmt package looks for Formatter before Stringer, but we want to use Stringer only. big.Int and big.Rat implement Formatter, and we embed them in our BigInt and BigRat types. To make sure that our String gets called rather than the inner Format, we put a non-matching stub Format method into this interface. This is ugly but very simple and cheap.

func (BigInt) Inner

func (i BigInt) Inner() Value

func (BigInt) ProgString

func (i BigInt) ProgString() string

func (BigInt) Rank

func (i BigInt) Rank() int

func (BigInt) Sprint

func (i BigInt) Sprint(c Context) string

func (BigInt) String

func (i BigInt) String() string

type BigRat

type BigRat struct {
	*big.Rat
}

func (BigRat) Eval

func (r BigRat) Eval(Context) Value

func (BigRat) Inner

func (r BigRat) Inner() Value

func (BigRat) ProgString

func (r BigRat) ProgString() string

func (BigRat) Rank

func (r BigRat) Rank() int

func (BigRat) Sprint

func (r BigRat) Sprint(c Context) string

func (BigRat) String

func (r BigRat) String() string

type BinaryExpr added in v0.3.8

type BinaryExpr struct {
	Op    string
	Left  Expr
	Right Expr
	// contains filtered or unexported fields
}

func (*BinaryExpr) Eval added in v0.3.8

func (b *BinaryExpr) Eval(context Context) Value

func (*BinaryExpr) ProgString added in v0.3.8

func (b *BinaryExpr) ProgString() string

type BinaryOp

type BinaryOp interface {
	EvalBinary(c Context, right, left Value) Value
}

BinaryOp is the interface implemented by a simple binary operator.

type Char

type Char rune

func (Char) Eval

func (c Char) Eval(Context) Value

func (Char) Inner

func (c Char) Inner() Value

func (Char) ProgString

func (c Char) ProgString() string

func (Char) Rank

func (c Char) Rank() int

func (Char) Sprint

func (c Char) Sprint(Context) string

func (Char) String

func (c Char) String() string

type ColonExpr added in v0.4.1

type ColonExpr struct {
	Cond  Expr
	Value Expr
}

ColonExpr is a conditional executor: expression ":" expression. It shortcuts execution of an StatementList.

func (*ColonExpr) Eval added in v0.4.1

func (c *ColonExpr) Eval(context Context) Value

func (*ColonExpr) ProgString added in v0.4.1

func (c *ColonExpr) ProgString() string

type Complex added in v0.2.0

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

func NewComplex added in v0.3.0

func NewComplex(c Context, u, v Value) Complex

func (Complex) Components added in v0.2.0

func (c Complex) Components() (Value, Value)

func (Complex) Eval added in v0.2.0

func (c Complex) Eval(Context) Value

func (Complex) Inner added in v0.2.0

func (c Complex) Inner() Value

func (Complex) ProgString added in v0.2.0

func (c Complex) ProgString() string

func (Complex) Rank added in v0.2.0

func (c Complex) Rank() int

func (Complex) Signum added in v0.3.1

func (c Complex) Signum(ctx Context) Complex

Signum returns:

0j0      if c == 0
c/abs c  if c != 0

func (Complex) Sprint added in v0.2.0

func (c Complex) Sprint(ctx Context) string

func (Complex) String added in v0.2.0

func (c Complex) String() string

type Context

type Context interface {
	// Config returns the configuration state for evaluation.
	Config() *config.Config

	// Local returns the named local variable.
	Local(name string) *Var

	// IsLocal reports whether the local variable is already defined.
	IsLocal(name string) bool

	// Global returns the named global variable.
	// It returns nil if there is no such variable.
	Global(name string) *Var

	// AssignGlobal assigns to the named global variable,
	// creating it if needed.
	AssignGlobal(name string, value Value)

	// Eval evaluates a list of expressions.
	Eval(exprs []Expr) []Value

	// EvalUnary evaluates a unary operator.
	EvalUnary(op string, right Value) Value

	// EvalBinary evaluates a binary operator.
	EvalBinary(left Value, op string, right Value) Value

	// UserDefined reports whether the specified op is user-defined.
	UserDefined(op string, isBinary bool) bool

	// Errorf reports an execution error and halts execution
	// by panicking with type Error.
	Errorf(format string, args ...interface{})

	// TraceIndent returns an indentation marker showing the depth of the stack.
	TraceIndent() string

	// TopOfStack returns the top frame on the stack, or nil if there is no stack.
	TopOfStack() *Frame

	// StackTrace prints the execution stack.
	StackTrace()

	// DisableTracing can disable tracing for the "failed" error catcher.
	DisableTracing(bool)

	// Pos and SetPos handle recording of source position for error reports.
	Pos() Pos
	SetPos(file string, line, offset int)
}

Context is the execution context for evaluation. The only implementation is ../exec/Context, but the interface is defined separately, here, because of the dependence on Expr and the import cycle that would otherwise result.

type Error

type Error struct {
	Pos Pos
	Err string
}

Error is the type we recognize as a recoverable run-time error.

func (Error) Error

func (err Error) Error() string

type Expr

type Expr interface {
	// ProgString returns the unambiguous representation of the
	// expression to be used in program source.
	ProgString() string

	Eval(Context) Value
}

Expr is the interface for a parsed expression. Also implemented by Value.

type Frame added in v0.4.2

type Frame struct {
	Op       string
	IsBinary bool
	Left     Expr
	Right    Expr
	Locals   []Variable
	Globals  []Variable
	Inited   bool // Until set, tracebacks will not attempt to evaluate this frame.
	Vars     Symtab
}

Frame holds the local execution context for a user-defined op. Used to print helpful error tracebacks. May one day hold the local variables themselves.

func (*Frame) String added in v0.5.0

func (f *Frame) String() string

type IfExpr added in v0.4.1

type IfExpr struct {
	Cond     Expr
	Body     StatementList
	ElseBody StatementList
}

IfExpr is a conditional expression: ":if" expression; statementList [":else" statementList] ":end" If there is an ":elif", it has been parsed into a properly nested ":else" ":if".

func (*IfExpr) Eval added in v0.4.1

func (i *IfExpr) Eval(context Context) Value

func (*IfExpr) ProgString added in v0.4.1

func (i *IfExpr) ProgString() string

type IndexExpr added in v0.3.8

type IndexExpr struct {
	Op    string
	Left  Expr
	Right []Expr
}

func (*IndexExpr) Eval added in v0.3.8

func (x *IndexExpr) Eval(context Context) Value

func (*IndexExpr) ProgString added in v0.3.8

func (x *IndexExpr) ProgString() string

type Int

type Int int64

func (Int) Eval

func (i Int) Eval(Context) Value

func (Int) Inner

func (i Int) Inner() Value

func (Int) ProgString

func (i Int) ProgString() string

func (Int) Rank

func (i Int) Rank() int

func (Int) Sprint

func (i Int) Sprint(c Context) string

func (Int) String

func (i Int) String() string

func (Int) ToBool

func (i Int) ToBool() bool

type Matrix

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

func NewMatrix

func NewMatrix(c Context, shape []int, data *Vector) *Matrix

NewMatrix makes a new matrix. The number of elements must fit in an Int.

func (*Matrix) Data

func (m *Matrix) Data() *Vector

Data returns the data of the matrix as a vector.

func (*Matrix) ElemSize

func (m *Matrix) ElemSize(c Context) int

ElemSize returns the size of each top-level element of the matrix. Given shape [a, b, c, ...] it is b*c*....

func (*Matrix) Eval

func (m *Matrix) Eval(Context) Value

func (*Matrix) Inner

func (m *Matrix) Inner() Value

func (*Matrix) ProgString

func (m *Matrix) ProgString() string

func (*Matrix) Rank

func (m *Matrix) Rank() int

func (*Matrix) Shape

func (m *Matrix) Shape() []int

Shape returns the shape of the matrix.

func (*Matrix) Size

func (m *Matrix) Size(c Context) int

Size returns number of elements of the matrix. Given shape [a, b, c, ...] it is a*b*c*....

func (*Matrix) Sprint

func (m *Matrix) Sprint(c Context) string

func (*Matrix) String

func (m *Matrix) String() string

type Pos added in v0.5.0

type Pos struct {
	File   string
	Line   int
	Offset int
}

Pos records a location in the input. It is used by Context.Errorf.

func (Pos) String added in v0.5.0

func (p Pos) String() string

type QuietValue added in v0.3.12

type QuietValue struct {
	Value
}

QuietValue is an implementation of Value that is created as the result of an assignment or print operator. It can be type-asserted to discover whether to avoid printing the results of the expression.

type RetExpr added in v0.4.1

type RetExpr struct {
	Expr  Expr  // In the parse tree.
	Value Value // After evaluation.
}

RetExpr is an early return from a function. See EvalFunctionBody.

func (*RetExpr) Eval added in v0.4.1

func (r *RetExpr) Eval(context Context) Value

func (*RetExpr) ProgString added in v0.4.1

func (r *RetExpr) ProgString() string

type Statement added in v0.5.0

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

A Statement is an expression, typically a line of input or element of a user-defined op. Unlike other expressions, it does not parse when created. Instead, only when first evaluated (through the Eval method) does it turn into a parsed expression. This is because the parse itself depends on external context that may be different at evaluation time than creation time, perhaps due to originally undefined variables or operators that have been defined since creation. One way this can arise is through mutual recursion:

op foo x = x==0: 1; bar x-1 op bar z = z==0: 0; foo z-1

Another issue is that whether an identifier is a variable or op may also depend on when it is evaluated:

1 j 2 # j is a binary operator; result 1j2 j = 5 # j is now a variable 1 j 2 # result: 1 5 2

Earlier versions of ivy parsed immediately, which caused a number of minor but niggling issues, including not being able to use j as a variable.

func NewStatement added in v0.5.0

func NewStatement(tokens []scan.Token, fileName string, inOperator bool) *Statement

NewStatement creates a statement (expression) defined by the tokens. inOperator records whether the statement is part of a user-defined op, which when true admits :ret expressions.

func (*Statement) Errorf added in v0.5.0

func (s *Statement) Errorf(format string, args ...interface{})

Called only during parsing.

func (*Statement) Eval added in v0.5.0

func (s *Statement) Eval(c Context) Value

func (*Statement) Parse added in v0.5.0

func (s *Statement) Parse(c Context) Expr

Parse parses the Statement into an Expr. Because it's the APL way, we parse right to left.

func (*Statement) ProgString added in v0.5.0

func (s *Statement) ProgString() string

func (*Statement) VarsAndRet added in v0.5.0

func (s *Statement) VarsAndRet() ([]string, bool)

VarsAndRet returns a list of identifiers (which may or may not be variables; we find out when evaluating) in the body of the statement. It also reports whether the statement has a :ret.

type StatementList added in v0.5.0

type StatementList []Expr

func (StatementList) Eval added in v0.5.0

func (s StatementList) Eval(context Context) Value

func (StatementList) ProgString added in v0.5.0

func (s StatementList) ProgString() string

type Symtab added in v0.4.2

type Symtab []*Var

Symtab is a symbol table, a slice of variables. Once placed in a Frame, it is of fixed size.

func (Symtab) String added in v0.5.0

func (s Symtab) String() string

type UnaryExpr added in v0.3.8

type UnaryExpr struct {
	Op    string
	Right Expr
	// contains filtered or unexported fields
}

func (*UnaryExpr) Eval added in v0.3.8

func (u *UnaryExpr) Eval(context Context) Value

func (*UnaryExpr) ProgString added in v0.3.8

func (u *UnaryExpr) ProgString() string

type UnaryOp

type UnaryOp interface {
	EvalUnary(c Context, right Value) Value
}

UnaryOp is the interface implemented by a simple unary operator.

type Value

type Value interface {
	// String is for internal debugging only. It uses default configuration
	// and puts parentheses around every value so it's clear when it is used.
	// All user output should call Sprint instead.
	String() string
	Sprint(Context) string

	// Eval evaluates (simplifies) the Value.
	Eval(Context) Value

	// Inner retrieves the value, without evaluation. But for Assignments,
	// it returns the right-hand side.
	Inner() Value

	// Rank returns the rank of the value: 0 for scalar, 1 for vector, etc.
	Rank() int

	// ProgString is like String, but suitable for program listing.
	// For instance, it ignores the user format for numbers and
	// puts quotes on chars, guaranteeing a correct representation.
	ProgString() string
	// contains filtered or unexported methods
}

func BinaryEach added in v0.3.7

func BinaryEach(c Context, lv Value, op string, rv Value) Value

BinaryEach computes the result of applying op to lv and rv, applying the "each" expansion depending on how many times @ appears on the left and right ends of op.

func Each added in v0.3.7

func Each(c Context, op string, v Value) Value

Each computes the result of running op on each element of v. The trailing @ has been removed.

func EvalBlock added in v0.4.1

func EvalBlock(context Context, fnName string, body StatementList) Value

EvalBlock evaluates the list of expressions inside a block, with the empty expression as the default value.

func EvalCharEqual added in v0.3.0

func EvalCharEqual(c Context, u Value, isEqualOp bool, v Value) (Value, bool)

EvalCharEqual handles == and != in a special case: If comparing a scalar against a Char, avoid the conversion. The logic of type promotion in EvalBinary otherwise interferes with comparison because it tries to force scalar types to be the same, and char doesn't convert to any other type.

func EvalFunctionBody added in v0.1.1

func EvalFunctionBody(context Context, fnName string, body StatementList, hasRet bool) (v Value)

EvalFunctionBody evaluates the list of expressions inside a function, with no default value.

func Index added in v0.1.12

func Index(context Context, top, left Expr, index []Expr) Value

Index returns left[index]. Left and index will be evaluated (right to left), while top is only for DebugProgString.

func ParseNumber added in v0.5.0

func ParseNumber(c Context, s string) (Value, error)

ParseNumber parses a string to create a number.

func Product

func Product(c Context, u Value, op string, v Value) Value

Product computes a compound product, such as an inner product "+.*" or outer product "o.*". The op is known to contain a period. The operands are all at least vectors, and for inner product they must both be vectors.

func QuoRem added in v0.3.0

func QuoRem(op string, c Context, a, b Value) (div, rem Value)

QuoRem uses Euclidean division to return the quotient and remainder for a/b. The quotient will be an integer, possibly negative; the remainder is always positive and may be fractional. Returned values satisfy the identity that

quo = a div b  such that
rem = a - b*quo  with 0 <= rem < |y|

See comment for math/big.Int.DivMod for details. Exported for testing.

func Reduce

func Reduce(c Context, op string, v Value) Value

Reduce computes a reduction such as +/. The slash has been removed.

func ReduceFirst added in v0.3.0

func ReduceFirst(c Context, op string, v Value) Value

ReduceFirst computes a reduction such as +/% along the first axis. The slash-percent has been removed.

func Scan

func Scan(c Context, op string, v Value) Value

Scan computes a scan of the op; the \ has been removed. It gives the successive values of reducing op through v. We must be right associative; that is the grammar.

func ScanFirst added in v0.3.0

func ScanFirst(c Context, op string, v Value) Value

ScanFirst computes a scan of the op along the first axis. The backslash-percent has been removed. It gives the successive values of reducing op through v. We must be right associative; that is the grammar.

type Var added in v0.3.12

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

A Var is a named variable in an Ivy execution.

func NewVar added in v0.3.8

func NewVar(name string, value Value, state VarState) *Var

NewVar returns a new Var with the given name and value.

func (*Var) Assign added in v0.3.12

func (v *Var) Assign(value Value)

Assign assigns value to v.

func (*Var) Name added in v0.3.12

func (v *Var) Name() string

Name returns v's name.

func (*Var) State added in v0.5.0

func (v *Var) State() VarState

State returns v's state.

func (*Var) Value added in v0.3.12

func (v *Var) Value() Value

Value returns v's current value.

type VarExpr added in v0.3.8

type VarExpr struct {
	Name string
	// contains filtered or unexported fields
}

VarExpr identifies a variable to be looked up and evaluated.

func NewVarExpr added in v0.3.12

func NewVarExpr(name string) *VarExpr

func (*VarExpr) Eval added in v0.3.8

func (e *VarExpr) Eval(c Context) Value

func (*VarExpr) ProgString added in v0.3.8

func (e *VarExpr) ProgString() string

type VarState added in v0.5.0

type VarState int

VarState holds the dynamic state of a variable, which is determined by the first action taken with it. Assuming we are in a user-defined op:

Unknown: Nothing has happened yet.
LocalVar: The first action was an assignment.
GlobalVar: The first action was a read (evaluation).

Within an op, a Var identifying a global variable holds only this state. The data itself is in the globals table. Implemented by the Assign and VarExpr.Eval functions.

const (
	Unknown VarState = iota
	LocalVar
	GlobalVar
)

type Variable added in v0.5.0

type Variable struct {
	Name  string
	State VarState
}

A Variable is a name mentioned in a function and records the first action done to the associated variable.

type Vector

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

func NewIntVector

func NewIntVector(elems ...int) *Vector

func NewVector

func NewVector(elems ...Value) *Vector

func NewVectorSeq added in v0.3.12

func NewVectorSeq(seq ...iter.Seq2[int, Value]) *Vector

NewVectorSeq creates a new vector from a sequence.

func (*Vector) All added in v0.3.8

func (v *Vector) All() iter.Seq2[int, Value]

All returns all the elements in v, for reading.

func (*Vector) AllChars

func (v *Vector) AllChars() bool

AllChars reports whether the vector contains only Chars.

func (*Vector) AllInts added in v0.1.6

func (v *Vector) AllInts() bool

AllInts reports whether the vector contains only Ints.

func (*Vector) At added in v0.3.8

func (v *Vector) At(i int) Value

At returns the i'th element of v.

func (*Vector) Eval

func (v *Vector) Eval(Context) Value

func (*Vector) Inner

func (v *Vector) Inner() Value

func (*Vector) Len added in v0.3.8

func (v *Vector) Len() int

Len returns the number of elements in v.

func (*Vector) ProgString

func (v *Vector) ProgString() string

func (*Vector) Rank

func (v *Vector) Rank() int

func (*Vector) Slice added in v0.3.8

func (v *Vector) Slice(i, j int) iter.Seq2[int, Value]

Slice returns a slice v[i:j], for reading.

func (*Vector) Sprint

func (v *Vector) Sprint(c Context) string

Sprint returns the formatting of v according to conf.

func (*Vector) String

func (v *Vector) String() string

type VectorExpr added in v0.3.8

type VectorExpr []Expr

VectorExpr holds a syntactic vector to be verified and evaluated.

func (VectorExpr) Eval added in v0.3.8

func (e VectorExpr) Eval(context Context) Value

func (VectorExpr) ProgString added in v0.3.8

func (e VectorExpr) ProgString() string

type WhileExpr added in v0.4.1

type WhileExpr struct {
	Cond Expr
	Body StatementList
}

WhileExpr is a loop expression: ":while" expression; statementList; ":end"

func (*WhileExpr) Eval added in v0.4.1

func (w *WhileExpr) Eval(context Context) Value

func (*WhileExpr) ProgString added in v0.4.1

func (w *WhileExpr) ProgString() string

Directories

Path Synopsis
Package persist implements a persistent slice data structure, similar to [Clojure's persistent vectors].
Package persist implements a persistent slice data structure, similar to [Clojure's persistent vectors].

Jump to

Keyboard shortcuts

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