memory align structs (#635)

feat: align most structs and add lint rule to enforce struct alignment
This commit is contained in:
Jesse 2022-10-19 16:19:15 +11:00 committed by GitHub
parent 8abb4aa639
commit 2655afd2bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 186 additions and 176 deletions

View File

@ -5,11 +5,24 @@ linters:
- stylecheck - stylecheck
- gochecknoinits - gochecknoinits
- golint - golint
- govet
issues: issues:
exclude-use-default: false exclude-use-default: false
exclude: exclude:
- "should have a package comment, unless it's in another file for this package" - "should have a package comment, unless it's in another file for this package"
- "the surrounding loop is unconditionally terminated" - "the surrounding loop is unconditionally terminated"
exclude-rules:
# ignore govet on non-critical files
- path: 'linter/*'
linters:
- govet
- path: '(.+)_test\.go'
linters:
- govet
linters-settings: linters-settings:
golint: golint:
min-confidence: 0 min-confidence: 0
govet:
enable-all: true
disable:
- shadow

View File

@ -22,7 +22,7 @@ import (
) )
// Identifier represents a variable / parameter / field name. // Identifier represents a variable / parameter / field name.
//+gen set // +gen set
type Identifier string type Identifier string
// Identifiers represents an Identifier slice. // Identifiers represents an Identifier slice.
@ -59,13 +59,13 @@ type Nodes []Node
// NodeBase holds fields common to all node types. // NodeBase holds fields common to all node types.
type NodeBase struct { type NodeBase struct {
LocRange LocationRange
// This is the fodder that precedes the first token of the node. // This is the fodder that precedes the first token of the node.
// If the node is left-recursive, i.e. the first token is actually // If the node is left-recursive, i.e. the first token is actually
// a token of a sub-expression, then Fodder is nil. // a token of a sub-expression, then Fodder is nil.
Fodder Fodder Fodder Fodder
Ctx Context Ctx Context
FreeVars Identifiers FreeVars Identifiers
LocRange LocationRange
} }
// NewNodeBase creates a new NodeBase from initial LocationRange and // NewNodeBase creates a new NodeBase from initial LocationRange and
@ -117,8 +117,8 @@ func (n *NodeBase) SetContext(context Context) {
// IfSpec represents an if-specification in a comprehension. // IfSpec represents an if-specification in a comprehension.
type IfSpec struct { type IfSpec struct {
IfFodder Fodder
Expr Node Expr Node
IfFodder Fodder
} }
// ForSpec represents a for-specification in a comprehension. // ForSpec represents a for-specification in a comprehension.
@ -135,34 +135,35 @@ type IfSpec struct {
// The if is attached to the y forspec. // The if is attached to the y forspec.
// //
// It desugares to: // It desugares to:
// flatMap(\x -> //
// flatMap(\y -> // flatMap(\x ->
// flatMap(\z -> [expr], arr3) // flatMap(\y ->
// arr2) // flatMap(\z -> [expr], arr3)
// arr3) // arr2)
// arr3)
type ForSpec struct { type ForSpec struct {
ForFodder Fodder ForFodder Fodder
VarFodder Fodder VarFodder Fodder
VarName Identifier
InFodder Fodder
Expr Node
Conditions []IfSpec Conditions []IfSpec
Outer *ForSpec Outer *ForSpec
Expr Node
VarName Identifier
InFodder Fodder
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Apply represents a function call // Apply represents a function call
type Apply struct { type Apply struct {
NodeBase Target Node
Target Node FodderLeft Fodder
FodderLeft Fodder Arguments Arguments
Arguments Arguments
// Always false if there were no arguments.
TrailingComma bool
TailStrict bool
FodderRight Fodder FodderRight Fodder
TailStrictFodder Fodder TailStrictFodder Fodder
NodeBase
// Always false if there were no arguments.
TrailingComma bool
TailStrict bool
} }
// NamedArgument represents a named argument to function call x=1. // NamedArgument represents a named argument to function call x=1.
@ -193,20 +194,20 @@ type Arguments struct {
// ApplyBrace represents e { }. Desugared to e + { }. // ApplyBrace represents e { }. Desugared to e + { }.
type ApplyBrace struct { type ApplyBrace struct {
NodeBase
Left Node Left Node
Right Node Right Node
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Array represents array constructors [1, 2, 3]. // Array represents array constructors [1, 2, 3].
type Array struct { type Array struct {
Elements []CommaSeparatedExpr
CloseFodder Fodder
NodeBase NodeBase
Elements []CommaSeparatedExpr
// Always false if there were no elements. // Always false if there were no elements.
TrailingComma bool TrailingComma bool
CloseFodder Fodder
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -214,12 +215,12 @@ type Array struct {
// ArrayComp represents array comprehensions (which are like Python list // ArrayComp represents array comprehensions (which are like Python list
// comprehensions) // comprehensions)
type ArrayComp struct { type ArrayComp struct {
NodeBase
Body Node Body Node
TrailingComma bool
TrailingCommaFodder Fodder TrailingCommaFodder Fodder
Spec ForSpec Spec ForSpec
CloseFodder Fodder CloseFodder Fodder
NodeBase
TrailingComma bool
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -229,12 +230,12 @@ type ArrayComp struct {
// After parsing, message can be nil indicating that no message was // After parsing, message can be nil indicating that no message was
// specified. This AST is elimiated by desugaring. // specified. This AST is elimiated by desugaring.
type Assert struct { type Assert struct {
NodeBase
Cond Node Cond Node
ColonFodder Fodder
Message Node Message Node
SemicolonFodder Fodder
Rest Node Rest Node
ColonFodder Fodder
SemicolonFodder Fodder
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -337,11 +338,11 @@ func (b BinaryOp) String() string {
// Binary represents binary operators. // Binary represents binary operators.
type Binary struct { type Binary struct {
NodeBase Right Node
Left Node Left Node
OpFodder Fodder OpFodder Fodder
Op BinaryOp NodeBase
Right Node Op BinaryOp
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -351,12 +352,12 @@ type Binary struct {
// After parsing, branchFalse can be nil indicating that no else branch // After parsing, branchFalse can be nil indicating that no else branch
// was specified. The desugarer fills this in with a LiteralNull // was specified. The desugarer fills this in with a LiteralNull
type Conditional struct { type Conditional struct {
NodeBase
Cond Node Cond Node
ThenFodder Fodder
BranchTrue Node BranchTrue Node
ElseFodder Fodder
BranchFalse Node BranchFalse Node
ThenFodder Fodder
ElseFodder Fodder
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -368,21 +369,21 @@ type Dollar struct{ NodeBase }
// Error represents the error e. // Error represents the error e.
type Error struct { type Error struct {
NodeBase
Expr Node Expr Node
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Function represents a function definition // Function represents a function definition
type Function struct { type Function struct {
NodeBase ParenLeftFodder Fodder
ParenLeftFodder Fodder
Parameters []Parameter
// Always false if there were no parameters.
TrailingComma bool
ParenRightFodder Fodder ParenRightFodder Fodder
Body Node Body Node
Parameters []Parameter
NodeBase
// Always false if there were no parameters.
TrailingComma bool
} }
// Parameter represents a parameter of function. // Parameter represents a parameter of function.
@ -391,9 +392,9 @@ type Function struct {
type Parameter struct { type Parameter struct {
NameFodder Fodder NameFodder Fodder
Name Identifier Name Identifier
CommaFodder Fodder
EqFodder Fodder EqFodder Fodder
DefaultArg Node DefaultArg Node
CommaFodder Fodder
LocRange LocationRange LocRange LocationRange
} }
@ -409,24 +410,24 @@ type CommaSeparatedID struct {
// Import represents import "file". // Import represents import "file".
type Import struct { type Import struct {
NodeBase
File *LiteralString File *LiteralString
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// ImportStr represents importstr "file". // ImportStr represents importstr "file".
type ImportStr struct { type ImportStr struct {
NodeBase
File *LiteralString File *LiteralString
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// ImportBin represents importbin "file". // ImportBin represents importbin "file".
type ImportBin struct { type ImportBin struct {
NodeBase
File *LiteralString File *LiteralString
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -436,24 +437,22 @@ type ImportBin struct {
// One of index and id will be nil before desugaring. After desugaring id // One of index and id will be nil before desugaring. After desugaring id
// will be nil. // will be nil.
type Index struct { type Index struct {
NodeBase
Target Node Target Node
// When Index is being used, this is the fodder before the '['. Index Node
// When Id is being used, this is the fodder before the '.'.
LeftBracketFodder Fodder
Index Node
// When Index is being used, this is the fodder before the ']'. // When Index is being used, this is the fodder before the ']'.
// When Id is being used, this is the fodder before the id. // When Id is being used, this is the fodder before the id.
RightBracketFodder Fodder RightBracketFodder Fodder
// When Index is being used, this is the fodder before the '['.
// When Id is being used, this is the fodder before the '.'.
LeftBracketFodder Fodder
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties //nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier Id *Identifier
NodeBase
} }
// Slice represents an array slice a[begin:end:step]. // Slice represents an array slice a[begin:end:step].
type Slice struct { type Slice struct {
NodeBase Target Node
Target Node
LeftBracketFodder Fodder LeftBracketFodder Fodder
// Each of these can be nil // Each of these can be nil
BeginIndex Node BeginIndex Node
@ -462,6 +461,7 @@ type Slice struct {
StepColonFodder Fodder StepColonFodder Fodder
Step Node Step Node
RightBracketFodder Fodder RightBracketFodder Fodder
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -469,15 +469,14 @@ type Slice struct {
// LocalBind is a helper struct for astLocal // LocalBind is a helper struct for astLocal
type LocalBind struct { type LocalBind struct {
VarFodder Fodder VarFodder Fodder
Variable Identifier
EqFodder Fodder
// If Fun is set then its body == Body. // If Fun is set then its body == Body.
Body Node Body Node
// There is no base fodder in Fun because there was no `function` keyword. EqFodder Fodder
Fun *Function Variable Identifier
// The fodder before the closing ',' or ';' (whichever it is) // The fodder before the closing ',' or ';' (whichever it is)
CloseFodder Fodder CloseFodder Fodder
// There is no base fodder in Fun because there was no `function` keyword.
Fun *Function
LocRange LocationRange LocRange LocationRange
} }
@ -486,9 +485,9 @@ type LocalBinds []LocalBind
// Local represents local x = e; e. After desugaring, functionSugar is false. // Local represents local x = e; e. After desugaring, functionSugar is false.
type Local struct { type Local struct {
NodeBase
Binds LocalBinds Binds LocalBinds
Body Node Body Node
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -508,8 +507,8 @@ type LiteralNull struct{ NodeBase }
// LiteralNumber represents a JSON number // LiteralNumber represents a JSON number
type LiteralNumber struct { type LiteralNumber struct {
NodeBase
OriginalString string OriginalString string
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -540,11 +539,11 @@ func (k LiteralStringKind) FullyEscaped() bool {
// LiteralString represents a JSON string // LiteralString represents a JSON string
type LiteralString struct { type LiteralString struct {
NodeBase
Value string Value string
Kind LiteralStringKind
BlockIndent string BlockIndent string
BlockTermIndent string BlockTermIndent string
NodeBase
Kind LiteralStringKind
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -588,24 +587,23 @@ const (
// ObjectField represents a field of an object or object comprehension. // ObjectField represents a field of an object or object comprehension.
// TODO(sbarzowski) consider having separate types for various kinds // TODO(sbarzowski) consider having separate types for various kinds
type ObjectField struct { type ObjectField struct {
Kind ObjectFieldKind
Hide ObjectFieldHide // (ignore if kind != astObjectFieldID/Expr/Str)
SuperSugar bool // +: (ignore if kind != astObjectFieldID/Expr/Str)
// f(x, y, z): ... (ignore if kind == astObjectAssert) // f(x, y, z): ... (ignore if kind == astObjectAssert)
// If Method is set then Expr2 == Method.Body. // If Method is set then Expr2 == Method.Body.
// There is no base fodder in Method because there was no `function` // There is no base fodder in Method because there was no `function`
// keyword. // keyword.
Method *Function Method *Function
Fodder1 Fodder
Expr1 Node // Not in scope of the object
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties //nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier Id *Identifier
Fodder2 Fodder Fodder2 Fodder
Fodder1 Fodder
OpFodder Fodder OpFodder Fodder
Expr2, Expr3 Node // In scope of the object (can see self).
CommaFodder Fodder CommaFodder Fodder
Expr1 Node // Not in scope of the object
Expr2, Expr3 Node // In scope of the object (can see self).
LocRange LocationRange LocRange LocationRange
Kind ObjectFieldKind
Hide ObjectFieldHide // (ignore if kind != astObjectFieldID/Expr/Str)
SuperSugar bool // +: (ignore if kind != astObjectFieldID/Expr/Str)
} }
// ObjectFieldLocalNoMethod creates a non-method local object field. // ObjectFieldLocalNoMethod creates a non-method local object field.
@ -627,22 +625,21 @@ type ObjectFields []ObjectField
// The trailing comma is only allowed if len(fields) > 0. Converted to // The trailing comma is only allowed if len(fields) > 0. Converted to
// DesugaredObject during desugaring. // DesugaredObject during desugaring.
type Object struct { type Object struct {
Fields ObjectFields
CloseFodder Fodder
NodeBase NodeBase
Fields ObjectFields
TrailingComma bool TrailingComma bool
CloseFodder Fodder
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// DesugaredObjectField represents a desugared object field. // DesugaredObjectField represents a desugared object field.
type DesugaredObjectField struct { type DesugaredObjectField struct {
Hide ObjectFieldHide
Name Node Name Node
Body Node Body Node
LocRange LocationRange
Hide ObjectFieldHide
PlusSuper bool PlusSuper bool
LocRange LocationRange
} }
// DesugaredObjectFields represents a DesugaredObjectField slice. // DesugaredObjectFields represents a DesugaredObjectField slice.
@ -653,33 +650,35 @@ type DesugaredObjectFields []DesugaredObjectField
// //
// The assertions either return true or raise an error. // The assertions either return true or raise an error.
type DesugaredObject struct { type DesugaredObject struct {
NodeBase
Asserts Nodes Asserts Nodes
Fields DesugaredObjectFields Fields DesugaredObjectFields
Locals LocalBinds Locals LocalBinds
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// ObjectComp represents object comprehension // ObjectComp represents object comprehension
// { [e]: e for x in e for.. if... }. //
// { [e]: e for x in e for.. if... }.
type ObjectComp struct { type ObjectComp struct {
NodeBase
Fields ObjectFields Fields ObjectFields
TrailingCommaFodder Fodder TrailingCommaFodder Fodder
TrailingComma bool
Spec ForSpec
CloseFodder Fodder CloseFodder Fodder
Spec ForSpec
NodeBase
TrailingComma bool
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Parens represents parentheses // Parens represents parentheses
// ( e ) //
// ( e )
type Parens struct { type Parens struct {
NodeBase
Inner Node Inner Node
CloseFodder Fodder CloseFodder Fodder
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -694,24 +693,24 @@ type Self struct{ NodeBase }
// Either index or identifier will be set before desugaring. After desugaring, id will be // Either index or identifier will be set before desugaring. After desugaring, id will be
// nil. // nil.
type SuperIndex struct { type SuperIndex struct {
NodeBase
// If super.f, the fodder before the '.'
// If super[e], the fodder before the '['.
DotFodder Fodder
Index Node
// If super.f, the fodder before the 'f' // If super.f, the fodder before the 'f'
// If super[e], the fodder before the ']'. // If super[e], the fodder before the ']'.
IDFodder Fodder IDFodder Fodder
Index Node
// If super.f, the fodder before the '.'
// If super[e], the fodder before the '['.
DotFodder Fodder
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties //nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier Id *Identifier
NodeBase
} }
// InSuper represents the e in super construct. // InSuper represents the e in super construct.
type InSuper struct { type InSuper struct {
NodeBase
Index Node Index Node
InFodder Fodder InFodder Fodder
SuperFodder Fodder SuperFodder Fodder
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -751,18 +750,18 @@ func (u UnaryOp) String() string {
// Unary represents unary operators. // Unary represents unary operators.
type Unary struct { type Unary struct {
NodeBase
Op UnaryOp
Expr Node Expr Node
NodeBase
Op UnaryOp
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Var represents variables. // Var represents variables.
type Var struct { type Var struct {
NodeBase
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties //nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id Identifier Id Identifier
NodeBase
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -66,10 +66,10 @@ const (
// FodderElement is a single piece of fodder. // FodderElement is a single piece of fodder.
type FodderElement struct { type FodderElement struct {
Comment []string
Kind FodderKind Kind FodderKind
Blanks int Blanks int
Indent int Indent int
Comment []string
} }
// MakeFodderElement is a helper function that checks some preconditions. // MakeFodderElement is a helper function that checks some preconditions.

View File

@ -28,10 +28,10 @@ type DiagnosticFileName string
// Source represents a source file. // Source represents a source file.
type Source struct { type Source struct {
Lines []string
// DiagnosticFileName is the imported path or a special string // DiagnosticFileName is the imported path or a special string
// for indicating stdin, extvars and other non-imported sources. // for indicating stdin, extvars and other non-imported sources.
DiagnosticFileName DiagnosticFileName DiagnosticFileName DiagnosticFileName
Lines []string
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -68,11 +68,11 @@ func LocationBefore(a Location, b Location) bool {
// LocationRange represents a range of a source file. // LocationRange represents a range of a source file.
type LocationRange struct { type LocationRange struct {
File *Source
// FileName should be the imported path or "" for snippets etc. // FileName should be the imported path or "" for snippets etc.
FileName string FileName string
Begin Location Begin Location
End Location // TODO(sbarzowski) inclusive? exclusive? a gap? End Location // TODO(sbarzowski) inclusive? exclusive? a gap?
File *Source
} }
// LocationRangeBetween returns a LocationRange containing both a and b. // LocationRangeBetween returns a LocationRange containing both a and b.
@ -164,7 +164,7 @@ func BuildSource(dFilename DiagnosticFileName, s string) *Source {
rest := lineBuf.String() rest := lineBuf.String()
// Stuff after last end-of-line (EOF or some more code) // Stuff after last end-of-line (EOF or some more code)
result = append(result, rest+"\n") result = append(result, rest+"\n")
return &Source{result, dFilename} return &Source{dFilename, result}
} }
func trimToLine(loc LocationRange, line int) LocationRange { func trimToLine(loc LocationRange, line int) LocationRange {
@ -187,11 +187,12 @@ func trimToLine(loc LocationRange, line int) LocationRange {
// LineBeginning returns the part of a line directly before LocationRange // LineBeginning returns the part of a line directly before LocationRange
// for example: // for example:
// local x = foo() //
// ^^^^^ <- LocationRange loc // local x = foo()
// then // ^^^^^ <- LocationRange loc
// local x = foo() // then
// ^^^^^^^^^^ <- lineBeginning(loc) // local x = foo()
// ^^^^^^^^^^ <- lineBeginning(loc)
func LineBeginning(loc *LocationRange) LocationRange { func LineBeginning(loc *LocationRange) LocationRange {
return LocationRange{ return LocationRange{
Begin: Location{Line: loc.Begin.Line, Column: 1}, Begin: Location{Line: loc.Begin.Line, Column: 1},
@ -203,11 +204,12 @@ func LineBeginning(loc *LocationRange) LocationRange {
// LineEnding returns the part of a line directly after LocationRange // LineEnding returns the part of a line directly after LocationRange
// for example: // for example:
// local x = foo() + test //
// ^^^^^ <- LocationRange loc // local x = foo() + test
// then // ^^^^^ <- LocationRange loc
// local x = foo() + test // then
// ^^^^^^^ <- lineEnding(loc) // local x = foo() + test
// ^^^^^^^ <- lineEnding(loc)
func LineEnding(loc *LocationRange) LocationRange { func LineEnding(loc *LocationRange) LocationRange {
return LocationRange{ return LocationRange{
Begin: loc.End, Begin: loc.End,

View File

@ -260,9 +260,9 @@ func builtinTrace(i *interpreter, x value, y value) (value, error) {
// time. It is equivalent to `local i = 42; func(i)`. It therefore has no // time. It is equivalent to `local i = 42; func(i)`. It therefore has no
// free variables and needs only an empty environment to execute. // free variables and needs only an empty environment to execute.
type astMakeArrayElement struct { type astMakeArrayElement struct {
ast.NodeBase
function *valueFunction function *valueFunction
index int ast.NodeBase
index int
} }
func builtinMakeArray(i *interpreter, szv, funcv value) (value, error) { func builtinMakeArray(i *interpreter, szv, funcv value) (value, error) {
@ -506,10 +506,10 @@ func builtinFilter(i *interpreter, funcv, arrv value) (value, error) {
} }
type sortData struct { type sortData struct {
err error
i *interpreter i *interpreter
thunks []*cachedThunk thunks []*cachedThunk
keys []value keys []value
err error
} }
func (d *sortData) Len() int { func (d *sortData) Len() int {
@ -1917,10 +1917,10 @@ func (b *ternaryBuiltin) Name() ast.Identifier {
type generalBuiltinFunc func(*interpreter, []value) (value, error) type generalBuiltinFunc func(*interpreter, []value) (value, error)
type generalBuiltinParameter struct { type generalBuiltinParameter struct {
name ast.Identifier
// Note that the defaults are passed as values rather than AST nodes like in Parameters. // Note that the defaults are passed as values rather than AST nodes like in Parameters.
// This spares us unnecessary evaluation. // This spares us unnecessary evaluation.
defaultValue value defaultValue value
name ast.Identifier
} }
// generalBuiltin covers cases that other builtin structures do not, // generalBuiltin covers cases that other builtin structures do not,
@ -1929,8 +1929,8 @@ type generalBuiltinParameter struct {
// at the same index. // at the same index.
type generalBuiltin struct { type generalBuiltin struct {
name ast.Identifier name ast.Identifier
params []generalBuiltinParameter
function generalBuiltinFunc function generalBuiltinFunc
params []generalBuiltinParameter
} }
func (b *generalBuiltin) parameters() []namedParameter { func (b *generalBuiltin) parameters() []namedParameter {

View File

@ -16,8 +16,8 @@ import (
// handlesTable is the set of active, valid Jsonnet allocated handles // handlesTable is the set of active, valid Jsonnet allocated handles
type handlesTable struct { type handlesTable struct {
mu sync.Mutex
handles map[uintptr]*handle handles map[uintptr]*handle
mu sync.Mutex
} }
type handle struct { type handle struct {

View File

@ -93,15 +93,14 @@ func usage(o io.Writer) {
} }
type config struct { type config struct {
inputFiles []string outputFile string
outputFile string evalMultiOutputDir string
filenameIsCode bool inputFiles []string
evalJpath []string
filenameIsCode bool
evalMulti bool evalMulti bool
evalStream bool evalStream bool
evalMultiOutputDir string
evalCreateOutputDirs bool evalCreateOutputDirs bool
evalJpath []string
} }
func makeConfig() config { func makeConfig() config {

View File

@ -71,13 +71,13 @@ func usage(o io.Writer) {
} }
type config struct { type config struct {
outputFile string
inputFiles []string
evalCreateOutputDirs bool evalCreateOutputDirs bool
filenameIsCode bool filenameIsCode bool
inPlace bool inPlace bool
inputFiles []string
options formatter.Options
outputFile string
test bool test bool
options formatter.Options
} }
func makeConfig() config { func makeConfig() config {

View File

@ -43,17 +43,15 @@ type ColorFormatter func(w io.Writer, f string, a ...interface{}) (n int, err er
var _ ErrorFormatter = &termErrorFormatter{} var _ ErrorFormatter = &termErrorFormatter{}
type termErrorFormatter struct { type termErrorFormatter struct {
// maxStackTraceSize is the maximum length of stack trace before cropping
maxStackTraceSize int
// Examples of current state of the art. // Examples of current state of the art.
// http://elm-lang.org/blog/compiler-errors-for-humans // http://elm-lang.org/blog/compiler-errors-for-humans
// https://clang.llvm.org/diagnostics.html // https://clang.llvm.org/diagnostics.html
color ColorFormatter color ColorFormatter
pretty bool
// sp is currently never set, but is used to format locations. // sp is currently never set, but is used to format locations.
sp *ast.SourceProvider sp *ast.SourceProvider
// maxStackTraceSize is the maximum length of stack trace before cropping
maxStackTraceSize int
pretty bool
} }
func (ef *termErrorFormatter) SetMaxStackTraceSize(size int) { func (ef *termErrorFormatter) SetMaxStackTraceSize(size int) {

View File

@ -70,6 +70,7 @@ func (c Contents) String() string {
return *(*string)(unsafe.Pointer(c.data)) return *(*string)(unsafe.Pointer(c.data))
} }
// Data returns content bytes
func (c Contents) Data() []byte { func (c Contents) Data() []byte {
return *c.data return *c.data
} }
@ -217,13 +218,13 @@ func (cache *importCache) importCode(importedFrom, importedPath string, i *inter
// FileImporter imports data from the filesystem. // FileImporter imports data from the filesystem.
type FileImporter struct { type FileImporter struct {
JPaths []string
fsCache map[string]*fsCacheEntry fsCache map[string]*fsCacheEntry
JPaths []string
} }
type fsCacheEntry struct { type fsCacheEntry struct {
exists bool
contents Contents contents Contents
exists bool
} }
func (importer *FileImporter) tryPath(dir, importedPath string) (found bool, contents Contents, foundHere string, err error) { func (importer *FileImporter) tryPath(dir, importedPath string) (found bool, contents Contents, foundHere string, err error) {

View File

@ -33,11 +33,11 @@ var packageNameStripperRegexp = regexp.MustCompile(`\b[a-zA-Z_]+[a-zA-Z_0-9]+\.`
// Options represents configuration option // Options represents configuration option
type Options struct { type Options struct {
StripPackageNames bool
HidePrivateFields bool
HomePackage string HomePackage string
VariableName string VariableName string
VariableDescription string VariableDescription string
StripPackageNames bool
HidePrivateFields bool
} }
// Config is the default config used when calling Dump // Config is the default config used when calling Dump
@ -48,7 +48,7 @@ var Config = Options{
VariableDescription: "", VariableDescription: "",
} }
type dumpState struct { type dumpState struct { // nolint:govet
w io.Writer w io.Writer
depth int depth int
config *Options config *Options

View File

@ -38,8 +38,8 @@ type StaticError interface {
} }
type staticError struct { type staticError struct {
loc ast.LocationRange
msg string msg string
loc ast.LocationRange
} }
func (err staticError) WithContext(context string) StaticError { func (err staticError) WithContext(context string) StaticError {

View File

@ -23,8 +23,8 @@ import (
) )
type importElem struct { type importElem struct {
key string
adjacentFodder ast.Fodder adjacentFodder ast.Fodder
key string
bind ast.LocalBind bind ast.LocalBind
} }
@ -123,7 +123,7 @@ func extractImportElems(binds ast.LocalBinds, after ast.Fodder) []importElem {
newBind.VarFodder = before newBind.VarFodder = before
theImport := bind.Body.(*ast.Import) theImport := bind.Body.(*ast.Import)
result = append(result, result = append(result,
importElem{theImport.File.Value, adjacent, newBind}) importElem{key: theImport.File.Value, adjacentFodder: adjacent, bind: newBind})
before = beforeNext before = beforeNext
} }
return result return result

View File

@ -144,7 +144,8 @@ func DirectChildren(node ast.Node) []ast.Node {
// It supports ASTs before and after desugaring. // It supports ASTs before and after desugaring.
// //
// TODO(sbarzowski) Make sure it works well with boundary cases like tailstrict arguments, // TODO(sbarzowski) Make sure it works well with boundary cases like tailstrict arguments,
// make it more precise. // make it more precise.
//
// Rules: // Rules:
// * (same-environment) They must be evaluated in the same environment as their parent // * (same-environment) They must be evaluated in the same environment as their parent
// * (not-direct) If they can be direct children, they should (and cannot be thunked). // * (not-direct) If they can be direct children, they should (and cannot be thunked).

View File

@ -147,15 +147,13 @@ func (tk tokenKind) String() string {
} }
type token struct { type token struct {
kind tokenKind // The type of the token
fodder ast.Fodder // Any fodder that occurs before this token fodder ast.Fodder // Any fodder that occurs before this token
data string // Content of the token if it is not a keyword data string // Content of the token if it is not a keyword
// Extra info for when kind == tokenStringBlock // Extra info for when kind == tokenStringBlock
stringBlockIndent string // The sequence of whitespace that indented the block. stringBlockIndent string // The sequence of whitespace that indented the block.
stringBlockTermIndent string // This is always fewer whitespace characters than in stringBlockIndent. stringBlockTermIndent string // This is always fewer whitespace characters than in stringBlockIndent.
loc ast.LocationRange
loc ast.LocationRange kind tokenKind // The type of the token
} }
// Tokens is a slice of token structs. // Tokens is a slice of token structs.
@ -283,8 +281,6 @@ type lexer struct {
input string // The input string input string // The input string
source *ast.Source source *ast.Source
pos position // Current position in input
tokens Tokens // The tokens that we've generated so far tokens Tokens // The tokens that we've generated so far
// Information about the token we are working on right now // Information about the token we are working on right now
@ -294,6 +290,8 @@ type lexer struct {
// Was the last rune the first rune on a line (ignoring initial whitespace). // Was the last rune the first rune on a line (ignoring initial whitespace).
freshLine bool freshLine bool
pos position // Current position in input
} }
const lexEOF = -1 const lexEOF = -1

View File

@ -32,15 +32,14 @@ import (
// TODO(sbarzowski) use it as a pointer in most places b/c it can sometimes be shared // TODO(sbarzowski) use it as a pointer in most places b/c it can sometimes be shared
// for example it can be shared between array elements and function arguments // for example it can be shared between array elements and function arguments
type environment struct { type environment struct {
selfBinding selfBinding
// Bindings introduced in this frame. The way previous bindings are treated // Bindings introduced in this frame. The way previous bindings are treated
// depends on the type of a frame. // depends on the type of a frame.
// If cleanEnv == true then previous bindings are ignored (it's a clean // If cleanEnv == true then previous bindings are ignored (it's a clean
// environment with just the variables we have here). // environment with just the variables we have here).
// If cleanEnv == false then if this frame doesn't contain a binding // If cleanEnv == false then if this frame doesn't contain a binding
// previous bindings will be used. // previous bindings will be used.
upValues bindingFrame upValues bindingFrame
selfBinding selfBinding
} }
func makeEnvironment(upValues bindingFrame, sb selfBinding) environment { func makeEnvironment(upValues bindingFrame, sb selfBinding) environment {
@ -64,20 +63,20 @@ func (i *interpreter) getCurrentStackTrace() []traceFrame {
} }
type callFrame struct { type callFrame struct {
// Tracing information about the place where it was called from.
trace traceElement
env environment
// True if it switches to a clean environment (function call or array element) // True if it switches to a clean environment (function call or array element)
// False otherwise, e.g. for local // False otherwise, e.g. for local
cleanEnv bool cleanEnv bool
// Tracing information about the place where it was called from.
trace traceElement
// Whether this frame can be removed from the stack when it doesn't affect // Whether this frame can be removed from the stack when it doesn't affect
// the evaluation result, but in case of an error, it won't appear on the // the evaluation result, but in case of an error, it won't appear on the
// stack trace. // stack trace.
// It's used for tail call optimization. // It's used for tail call optimization.
trimmable bool trimmable bool
env environment
} }
func dumpCallFrame(c *callFrame) string { func dumpCallFrame(c *callFrame) string {
@ -95,10 +94,10 @@ func dumpCallFrame(c *callFrame) string {
} }
type callStack struct { type callStack struct {
currentTrace traceElement
stack []*callFrame
calls int calls int
limit int limit int
stack []*callFrame
currentTrace traceElement
} }
func dumpCallStack(c *callStack) string { func dumpCallStack(c *callStack) string {
@ -242,10 +241,8 @@ func makeCallStack(limit int) callStack {
// Keeps current execution context and evaluates things // Keeps current execution context and evaluates things
type interpreter struct { type interpreter struct {
// Current stack. It is used for: // Output stream for trace() for
// 1) Keeping environment (object we're in, variables) traceOut io.Writer
// 2) Diagnostic information in case of failure
stack callStack
// External variables // External variables
extVars map[string]*cachedThunk extVars map[string]*cachedThunk
@ -259,8 +256,10 @@ type interpreter struct {
// Keeps imports // Keeps imports
importCache *importCache importCache *importCache
// Output stream for trace() for // Current stack. It is used for:
traceOut io.Writer // 1) Keeping environment (object we're in, variables)
// 2) Diagnostic information in case of failure
stack callStack
} }
// Map union, b takes precedence when keys collide. // Map union, b takes precedence when keys collide.
@ -414,7 +413,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) {
if field.PlusSuper { if field.PlusSuper {
f = &plusSuperUnboundField{f} f = &plusSuperUnboundField{f}
} }
fields[fieldName] = simpleObjectField{field.Hide, f} fields[fieldName] = simpleObjectField{f, field.Hide}
} }
var asserts []unboundField var asserts []unboundField
for _, assert := range node.Asserts { for _, assert := range node.Asserts {
@ -1181,7 +1180,7 @@ func buildStdObject(i *interpreter) (*valueObject, error) {
} }
for name, value := range builtinFields { for name, value := range builtinFields {
obj.fields[name] = simpleObjectField{ast.ObjectFieldHidden, value} obj.fields[name] = simpleObjectField{value, ast.ObjectFieldHidden}
} }
return objVal.(*valueObject), nil return objVal.(*valueObject), nil
} }
@ -1231,7 +1230,7 @@ func prepareExtVars(i *interpreter, ext vmExtMap, kind string) map[string]*cache
func buildObject(hide ast.ObjectFieldHide, fields map[string]value) *valueObject { func buildObject(hide ast.ObjectFieldHide, fields map[string]value) *valueObject {
fieldMap := simpleObjectFieldMap{} fieldMap := simpleObjectFieldMap{}
for name, v := range fields { for name, v := range fields {
fieldMap[name] = simpleObjectField{hide, &readyValue{v}} fieldMap[name] = simpleObjectField{&readyValue{v}, hide}
} }
return makeValueSimpleObject(bindingFrame{}, fieldMap, nil, nil) return makeValueSimpleObject(bindingFrame{}, fieldMap, nil, nil)
} }

View File

@ -20,8 +20,8 @@ import "github.com/google/go-jsonnet/ast"
// RuntimeError is an error discovered during evaluation of the program // RuntimeError is an error discovered during evaluation of the program
type RuntimeError struct { type RuntimeError struct {
StackTrace []traceFrame
Msg string Msg string
StackTrace []traceFrame
} }
func makeRuntimeError(msg string, stackTrace []traceFrame) RuntimeError { func makeRuntimeError(msg string, stackTrace []traceFrame) RuntimeError {
@ -40,8 +40,8 @@ func (err RuntimeError) Error() string {
// traceFrame is tracing information about a single frame of the call stack. // traceFrame is tracing information about a single frame of the call stack.
// TODO(sbarzowski) the difference from traceElement. Do we even need this? // TODO(sbarzowski) the difference from traceElement. Do we even need this?
type traceFrame struct { type traceFrame struct {
Loc ast.LocationRange
Name string Name string
Loc ast.LocationRange
} }
func traceElementToTraceFrame(trace traceElement) traceFrame { func traceElementToTraceFrame(trace traceElement) traceFrame {

View File

@ -18,6 +18,7 @@ package jsonnet
import ( import (
"fmt" "fmt"
"github.com/google/go-jsonnet/ast" "github.com/google/go-jsonnet/ast"
) )
@ -254,9 +255,9 @@ func makeClosure(env environment, function *ast.Function) *closure {
// NativeFunction represents a function implemented in Go. // NativeFunction represents a function implemented in Go.
type NativeFunction struct { type NativeFunction struct {
Name string
Func func([]interface{}) (interface{}, error) Func func([]interface{}) (interface{}, error)
Params ast.Identifiers Params ast.Identifiers
Name string
} }
// evalCall evaluates a call to a NativeFunction and returns the result. // evalCall evaluates a call to a NativeFunction and returns the result.

View File

@ -397,8 +397,8 @@ func (f *valueFunction) getType() *valueType {
} }
type namedParameter struct { type namedParameter struct {
name ast.Identifier
defaultArg ast.Node defaultArg ast.Node
name ast.Identifier
} }
type callArguments struct { type callArguments struct {
@ -408,8 +408,8 @@ type callArguments struct {
} }
type namedCallArgument struct { type namedCallArgument struct {
name ast.Identifier
pv *cachedThunk pv *cachedThunk
name ast.Identifier
} }
func args(xs ...*cachedThunk) callArguments { func args(xs ...*cachedThunk) callArguments {
@ -525,9 +525,9 @@ type uncachedObject interface {
} }
type objectLocal struct { type objectLocal struct {
name ast.Identifier
// Locals may depend on self and super so they are unbound fields and not simply thunks // Locals may depend on self and super so they are unbound fields and not simply thunks
node ast.Node node ast.Node
name ast.Identifier
} }
// simpleObject represents a flat object (no inheritance). // simpleObject represents a flat object (no inheritance).
@ -605,8 +605,8 @@ func makeValueSimpleObject(b bindingFrame, fields simpleObjectFieldMap, asserts
type simpleObjectFieldMap map[string]simpleObjectField type simpleObjectFieldMap map[string]simpleObjectField
type simpleObjectField struct { type simpleObjectField struct {
hide ast.ObjectFieldHide
field unboundField field unboundField
hide ast.ObjectFieldHide
} }
// unboundField is a field that doesn't know yet in which object it is. // unboundField is a field that doesn't know yet in which object it is.
@ -620,11 +620,11 @@ type unboundField interface {
// Example: // Example:
// (A + B) + C // (A + B) + C
// //
// + // +
// / \ // / \
// + C // + C
// / \ // / \
// A B // A B
// //
// It is possible to create an arbitrary binary tree. // It is possible to create an arbitrary binary tree.
// Note however, that because + is associative the only thing that matters // Note however, that because + is associative the only thing that matters
@ -632,7 +632,6 @@ type unboundField interface {
// //
// This represenation allows us to implement "+" in O(1), // This represenation allows us to implement "+" in O(1),
// but requires going through the tree and trying subsequent leafs for field access. // but requires going through the tree and trying subsequent leafs for field access.
//
type extendedObject struct { type extendedObject struct {
left, right uncachedObject left, right uncachedObject
totalInheritanceSize int totalInheritanceSize int

10
vm.go
View File

@ -36,7 +36,7 @@ import (
// VM is the core interpreter and is the touchpoint used to parse and execute // VM is the core interpreter and is the touchpoint used to parse and execute
// Jsonnet. // Jsonnet.
type VM struct { type VM struct { //nolint:govet
MaxStack int MaxStack int
ext vmExtMap ext vmExtMap
tla vmExtMap tla vmExtMap
@ -59,12 +59,12 @@ const (
// External variable or top level argument provided before execution // External variable or top level argument provided before execution
type vmExt struct { type vmExt struct {
// the kind of external variable that is specified.
kind extKind
// jsonnet code to evaluate (kind=extKindCode) or string to pass (kind=extKindVar)
value string
// the specified node for kind=extKindNode // the specified node for kind=extKindNode
node ast.Node node ast.Node
// jsonnet code to evaluate (kind=extKindCode) or string to pass (kind=extKindVar)
value string
// the kind of external variable that is specified.
kind extKind
} }
type vmExtMap map[string]vmExt type vmExtMap map[string]vmExt