variables

package
v0.0.0-...-ae32867 Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2020 License: BSD-3-Clause Imports: 7 Imported by: 0

Documentation

Overview

Package variables implements variables for programming languages similar to those in MetaFont and MetaPost.

Variables are complex things in MetaFont/MetaPost. These are legal:

metafont> showvariable x;
x=1
x[]=numeric
x[][]=numeric
x[][][]=numeric
x[][][][]=numeric
x[]r=numeric
x[]r[]=numeric
...

Identifier-strings are called "tags". In the example above, 'x' is a tag and 'r' is a suffix.

Array variables may be referenced without brackets, if the subscript is just a numeric literal, i.e. x[2]r and x2r refer to the same variable. We do not rely on the parser to decipher these kinds of variable names for us, but rather break up x2r16a => x[2]r[16]a by hand. However, the parser will split up array indices in brackets, for the subscript may be a complex expression ("x[ypart ((8,5) rotated 20)]" is a valid expression in MetaFont). Things are further complicated by the fact that subscripts are allowed to be decimals: x[1.2] is valid, and may be typed "x1.2".

metafont> x[ypart ((8,5) rotated 20)] = 1;
## x7.4347=1

I don't know if this makes sense in practice, but let's try to implement it -- it might be fun!

I did reject some of MetaFont's conventions, however, for the sake of simlicity: Types are inherited from the tag, i.e. if x is of type numeric, then x[2]r is of type numeric, too. This is different from MetaFont, where x2r may be of a different type than x2. Nevertheless, I'll stick to my interpretation, which I find less confusing.

The implementation currently is tightly coupled to the ANTLR V4 parser generator. Using ANTLR vor this task is a bit of overkill. Maybe I'll some day write a recursive descent parser from scratch as a substitute.

BSD License

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of Norbert Pillmayer nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewPMMPVarDecl

func NewPMMPVarDecl(nm string) runtime.Symbol

Create and initialize a new variable type declaration. This will be passed as a symbol-creator to the symbol table.

func NewPMMPVarRef

func NewPMMPVarRef(tagName string) runtime.Symbol

Symbol-creator for symbol table: creates tag symbol. Do not use this for pair variables !!

func T

func T() tracing.Trace

We're tracing to the InterpreterTracer

func TypeString

func TypeString(vt VariableType) string

Helper: get a type as string

Types

type PMMPVarDecl

type PMMPVarDecl struct {
	runtime.StdSymbol              // to use this we will have to override getName()
	Parent            *PMMPVarDecl // e.g., x <- [] <- suffix(a)
	BaseTag           *PMMPVarDecl // e.g., x // this pointer should never be nil
}

MetaFont declares variables explicitly ("numeric x;") or dynamically ("x=1" ⟹ x is of type numeric). Dynamic variable use is permitted for numeric variables only. All other types must be declared. Declaration is for tags only, i.e. the "x" in "x2r". This differs from MetaFont, where x2r can have a separate type from x.

We build up a doubly-linked tree of variable declarations to describe a variable with a single defining tag. The tag is the entity that goes to the symbol table (of a scope). Suffixes and subscripts are attached to the tag, but invisible as symbols.

Example:

numeric x; x2r := 7; x.b := 77;

Result:

tag = "x"  of type NumericType ⟹ into symbol table of a scope
   +-- suffix ".b" of type ComplexSuffix         "x.b"
   +-- subscript "[]" of type ComplexArray:      "x[]"
       +--- suffix ".r" of type ComplexSuffix:  "x[].r"

func CreatePMMPVarDecl

func CreatePMMPVarDecl(nm string, tp VariableType, parent *PMMPVarDecl) *PMMPVarDecl

Convenience function to create and initialize a type declaration. Callers provide a (usually complex) type and an optional parent. If the parent is given and already has a child / suffix-partial with the same signature as the one to create, this function will not create a new partial, but provide the existing one.

func (*PMMPVarDecl) AppendToVarDecl

func (d *PMMPVarDecl) AppendToVarDecl(v *PMMPVarDecl) *PMMPVarDecl

Append a complex type partial (suffix or array) to a parent identifier. Will not append the partial, if a partial with this name already exists (as a child).

func (*PMMPVarDecl) GetBaseType

func (d *PMMPVarDecl) GetBaseType() VariableType

Returns the type of the base tag.

func (*PMMPVarDecl) GetFullName

func (d *PMMPVarDecl) GetFullName() string

Get the full name of a type declaration, starting with the base tag. x <- array <- suffix(a) gives "x[].a", which is a bit more verbose than MetaFont's response. I prefer this one.

func (*PMMPVarDecl) GetName

func (d *PMMPVarDecl) GetName() string

Get isolated name of declaration partial (tag, array or suffix).

func (*PMMPVarDecl) ShowDeclarations

func (d *PMMPVarDecl) ShowDeclarations(s *bytes.Buffer) *bytes.Buffer

Show the variable declarations for a tag.

func (*PMMPVarDecl) String

func (d *PMMPVarDecl) String() string

Expressive Stringer implementation.

func (*PMMPVarDecl) Type

func (d *PMMPVarDecl) Type() VariableType

type PMMPVarRef

type PMMPVarRef struct {
	runtime.StdSymbol // store by normalized name

	Decl *PMMPVarDecl // type declaration for this variable

	Value interface{} // if known: has a value (numeric, pair, path, ...)
	// contains filtered or unexported fields
}

Variable reference look like "x", "x2", "hello.world" or "a[4.32].b". Variable references always refer to variable declarations (see code segments above.), which define the type and structure of the variable.

The declaration may have partials of type subscript. For every such partial the reference needs a decimal subscript, which we will store in an array of subscripts.

Example:

x[2.8].b[1] => subscripts = [2.8, 1]

Variable references can have a value (of type interface{}).

func CreatePMMPPairTypeVarRef

func CreatePMMPPairTypeVarRef(decl *PMMPVarDecl, value interface{}, indices []dec.Decimal) *PMMPVarRef

Create a pair variable reference. Low level method.

func CreatePMMPVarRef

func CreatePMMPVarRef(decl *PMMPVarDecl, value interface{}, indices []dec.Decimal) *PMMPVarRef

Create a variable reference. Low level method.

func (*PMMPVarRef) GetFullName

func (v *PMMPVarRef) GetFullName() string

Get the full normalized (canonical) name of a variable, i.e.

"x[2].r".

func (*PMMPVarRef) GetName

func (v *PMMPVarRef) GetName() string

This method returns the full nomalized name, i.e. "x[2].r". This enables us to store the variable in a symbol table. Overrides GetName() of interface Symbol.

func (*PMMPVarRef) GetSuffixesString

func (v *PMMPVarRef) GetSuffixesString() string

Strip the base tag string off of a variable and return all the suffxies as string.

func (*PMMPVarRef) GetValue

func (v *PMMPVarRef) GetValue() interface{}

Interface runtime.Assignable

func (*PMMPVarRef) IsKnown

func (v *PMMPVarRef) IsKnown() bool

Interface runtime.Assignable

func (*PMMPVarRef) IsPair

func (v *PMMPVarRef) IsPair() bool

Predicate: is this variable of type pair?

func (*PMMPVarRef) PullValue

func (v *PMMPVarRef) PullValue()

Whenever a pair part (x-part or y-part) is set, it sends a message to the parent pair variable to pull the value. If both parts are known and a numeric value is set, the parent pair creates a combined pair value.

func (*PMMPVarRef) Reincarnate

func (v *PMMPVarRef) Reincarnate() int

Set a new ID for a variable reference. Whenever variables become re-incarnated, a new serial ID is needed. Re-incarnation happens, whenever a variable goes out of scope, but is still relevant in the LEQ-system. The variables' name continues to live on in a new incarnation, while the out-of-scope variable lives on with the old serial.

Returns the old serial ID.

func (*PMMPVarRef) SetValue

func (v *PMMPVarRef) SetValue(val interface{})

Interface runtime.Assignable

func (*PMMPVarRef) String

func (v *PMMPVarRef) String() string

Expressive Stringer implementation.

func (*PMMPVarRef) Type

func (v *PMMPVarRef) Type() VariableType

Type returns the variable's type.

func (*PMMPVarRef) ValueString

func (v *PMMPVarRef) ValueString() string

Get the value of a variable as a string, if known. Otherwise return the tag name or type, depending on the variable type.

func (*PMMPVarRef) XPart

func (v *PMMPVarRef) XPart() *PairPartRef

Get the x-part of a pair variable

func (*PMMPVarRef) YPart

func (v *PMMPVarRef) YPart() *PairPartRef

Get the y-part of a pair variable

type PairPartRef

type PairPartRef struct {
	Id      int         // serial ID
	Pairvar *PMMPVarRef // pair parent
	Value   interface{} // if known: has a value (numeric)
}

Variables of type pair will use two sub-symbols for the x-part and y-part of the pair respectively. We will connect them using the sibling-link (x-part) and child-link (y-part) of the PMMPVarRef. Both parts link back to the pair variable.

We need a different serial ID for the y-part, as it will be used as a variable index in a system of linear equations LEQ. Otherwise x-part and y-part would not be distinguishable for the LEQ.

func (*PairPartRef) GetFirstChild

func (ppart *PairPartRef) GetFirstChild() runtime.TreeNode

Filler for interface TreeNode. Never called.

func (*PairPartRef) GetID

func (ppart *PairPartRef) GetID() int

Returns the serial ID for a pair variable's part.

func (*PairPartRef) GetName

func (ppart *PairPartRef) GetName() string

Pair parts (x-part or y-part) return the name of their parent pair symbol, prepending "xpart" or "ypart" respectively. This name is constant and may be used to store the pair part in a symbol table.

func (*PairPartRef) GetSibling

func (ppart *PairPartRef) GetSibling() runtime.TreeNode

Filler for interface TreeNode. Never called.

func (*PairPartRef) GetValue

func (ppart *PairPartRef) GetValue() interface{}

Get the x-part value of a pair.

Interface runtime.Assignable

func (*PairPartRef) IsKnown

func (ppart *PairPartRef) IsKnown() bool

Interface runtime.Assignable

func (*PairPartRef) SetFirstChild

func (ppart *PairPartRef) SetFirstChild(tn runtime.TreeNode)

Filler for interface TreeNode. Never called.

func (*PairPartRef) SetSibling

func (ppart *PairPartRef) SetSibling(runtime.TreeNode)

Filler for interface TreeNode. Never called.

func (*PairPartRef) SetValue

func (ppart *PairPartRef) SetValue(val interface{})

Interface runtime.Assignable

func (*PairPartRef) Type

func (ppart *PairPartRef) Type() VariableType

Interface Typed.

type VariableType

type VariableType int8

VariableType represents the type of a variable (obviously).

const (
	Undefined VariableType = iota
	NumericType
	PairType
	PathType
	ColorType
	PenType
	BoxType
	FrameType
	VardefType
	ComplexArray
	ComplexSuffix
)

Predefined variable types

func TypeFromString

func TypeFromString(str string) VariableType

Helper: get a type from a string

Directories

Path Synopsis
Package grammar contains generated Go code produced by ANTLR V4.
Package grammar contains generated Go code produced by ANTLR V4.
Package varparse implements a parser to get variable references from strings.
Package varparse implements a parser to get variable references from strings.

Jump to

Keyboard shortcuts

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