mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-28 08:51:01 +02:00
Make golangci-lint happy
Some of the suggestions are minor bug fixes (missing error handling).
This commit is contained in:
parent
803ad646cb
commit
9ada769ce4
14
ast/ast.go
14
ast/ast.go
@ -429,7 +429,8 @@ type Index struct {
|
||||
// When Index is being used, this is the fodder before the ']'.
|
||||
// When Id is being used, this is always empty.
|
||||
RightBracketFodder Fodder
|
||||
Id *Identifier
|
||||
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
|
||||
Id *Identifier
|
||||
}
|
||||
|
||||
// Slice represents an array slice a[begin:end:step].
|
||||
@ -576,9 +577,10 @@ type ObjectField struct {
|
||||
// If Method is set then Expr2 == Method.Body.
|
||||
// There is no base fodder in Method because there was no `function`
|
||||
// keyword.
|
||||
Method *Function
|
||||
Fodder1 Fodder
|
||||
Expr1 Node // Not in scope of the object
|
||||
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
|
||||
Id *Identifier
|
||||
Fodder2 Fodder
|
||||
OpFodder Fodder
|
||||
@ -676,7 +678,8 @@ type SuperIndex struct {
|
||||
// If super.f, the fodder before the 'f'
|
||||
// If super[e], the fodder before the ']'.
|
||||
IDFodder Fodder
|
||||
Id *Identifier
|
||||
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
|
||||
Id *Identifier
|
||||
}
|
||||
|
||||
// InSuper represents the e in super construct.
|
||||
@ -734,6 +737,7 @@ type Unary struct {
|
||||
// Var represents variables.
|
||||
type Var struct {
|
||||
NodeBase
|
||||
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
|
||||
Id Identifier
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func MakeFodderElement(kind FodderKind, blanks int, indent int, comment []string
|
||||
panic(fmt.Sprintf("FodderInterstitial but comment == %v.", comment))
|
||||
}
|
||||
if kind == FodderParagraph && len(comment) == 0 {
|
||||
panic(fmt.Sprintf("FodderParagraph but comment was empty"))
|
||||
panic("FodderParagraph but comment was empty")
|
||||
}
|
||||
return FodderElement{Kind: kind, Blanks: blanks, Indent: indent, Comment: comment}
|
||||
}
|
||||
|
@ -45,7 +45,10 @@ func (l *Location) String() string {
|
||||
return fmt.Sprintf("%v:%v", l.Line, l.Column)
|
||||
}
|
||||
|
||||
func locationBefore(a Location, b Location) bool {
|
||||
// LocationBefore returns whether one code location
|
||||
// refers to the location closer to the beginning
|
||||
// of the file than the other one.
|
||||
func LocationBefore(a Location, b Location) bool {
|
||||
if a.Line != b.Line {
|
||||
return a.Line < b.Line
|
||||
}
|
||||
|
225
builtins.go
225
builtins.go
@ -182,7 +182,7 @@ func builtinLength(i *interpreter, trace traceElement, x value) (value, error) {
|
||||
case valueString:
|
||||
num = x.length()
|
||||
case *valueFunction:
|
||||
for _, param := range x.Parameters() {
|
||||
for _, param := range x.parameters() {
|
||||
if param.defaultArg == nil {
|
||||
num++
|
||||
}
|
||||
@ -275,9 +275,7 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, elem := range returned.elements {
|
||||
elems = append(elems, elem)
|
||||
}
|
||||
elems = append(elems, returned.elements...)
|
||||
}
|
||||
return makeValueArray(elems), nil
|
||||
}
|
||||
@ -295,13 +293,9 @@ func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueA
|
||||
continue
|
||||
case *valueArray:
|
||||
if !first {
|
||||
for _, subElem := range sep.elements {
|
||||
result = append(result, subElem)
|
||||
}
|
||||
}
|
||||
for _, subElem := range v.elements {
|
||||
result = append(result, subElem)
|
||||
result = append(result, sep.elements...)
|
||||
}
|
||||
result = append(result, v.elements...)
|
||||
default:
|
||||
return nil, i.typeErrorSpecific(elemValue, &valueArray{}, trace)
|
||||
}
|
||||
@ -435,14 +429,6 @@ func (d *sortData) Sort() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func arrayFromThunks(vs []value) *valueArray {
|
||||
thunks := make([]*cachedThunk, len(vs))
|
||||
for i := range vs {
|
||||
thunks[i] = readyThunk(vs[i])
|
||||
}
|
||||
return makeValueArray(thunks)
|
||||
}
|
||||
|
||||
func builtinSort(i *interpreter, trace traceElement, arguments []value) (value, error) {
|
||||
arrv := arguments[0]
|
||||
keyFv := arguments[1]
|
||||
@ -468,7 +454,10 @@ func builtinSort(i *interpreter, trace traceElement, arguments []value) (value,
|
||||
}
|
||||
}
|
||||
|
||||
data.Sort()
|
||||
err = data.Sort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return makeValueArray(data.thunks), nil
|
||||
}
|
||||
@ -705,8 +694,8 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
runes := []rune(vStr.getGoString())
|
||||
for _, r := range runes {
|
||||
str := vStr.getGoString()
|
||||
for _, r := range str {
|
||||
n := int(r)
|
||||
msg, ok := sanityCheck(n)
|
||||
if !ok {
|
||||
@ -714,7 +703,7 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro
|
||||
}
|
||||
}
|
||||
|
||||
byteArr = []byte(string(vStr.getGoString()))
|
||||
byteArr = []byte(str)
|
||||
case *valueArray:
|
||||
vArr, err := i.getArray(input, trace)
|
||||
if err != nil {
|
||||
@ -1227,9 +1216,9 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value)
|
||||
type unaryBuiltinFunc func(*interpreter, traceElement, value) (value, error)
|
||||
|
||||
type unaryBuiltin struct {
|
||||
name ast.Identifier
|
||||
function unaryBuiltinFunc
|
||||
parameters ast.Identifiers
|
||||
name ast.Identifier
|
||||
function unaryBuiltinFunc
|
||||
params ast.Identifiers
|
||||
}
|
||||
|
||||
func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement {
|
||||
@ -1238,7 +1227,7 @@ func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement {
|
||||
}
|
||||
|
||||
func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
flatArgs := flattenArgs(args, b.Parameters(), []value{})
|
||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||
builtinTrace := getBuiltinTrace(trace, b.name)
|
||||
x, err := flatArgs[0].getValue(i, trace)
|
||||
if err != nil {
|
||||
@ -1247,10 +1236,10 @@ func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceE
|
||||
return b.function(i, builtinTrace, x)
|
||||
}
|
||||
|
||||
func (b *unaryBuiltin) Parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.parameters))
|
||||
func (b *unaryBuiltin) parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.params))
|
||||
for i := range ret {
|
||||
ret[i].name = b.parameters[i]
|
||||
ret[i].name = b.params[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -1262,13 +1251,13 @@ func (b *unaryBuiltin) Name() ast.Identifier {
|
||||
type binaryBuiltinFunc func(*interpreter, traceElement, value, value) (value, error)
|
||||
|
||||
type binaryBuiltin struct {
|
||||
name ast.Identifier
|
||||
function binaryBuiltinFunc
|
||||
parameters ast.Identifiers
|
||||
name ast.Identifier
|
||||
function binaryBuiltinFunc
|
||||
params ast.Identifiers
|
||||
}
|
||||
|
||||
func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
flatArgs := flattenArgs(args, b.Parameters(), []value{})
|
||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||
builtinTrace := getBuiltinTrace(trace, b.name)
|
||||
x, err := flatArgs[0].getValue(i, trace)
|
||||
if err != nil {
|
||||
@ -1281,10 +1270,10 @@ func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace trace
|
||||
return b.function(i, builtinTrace, x, y)
|
||||
}
|
||||
|
||||
func (b *binaryBuiltin) Parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.parameters))
|
||||
func (b *binaryBuiltin) parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.params))
|
||||
for i := range ret {
|
||||
ret[i].name = b.parameters[i]
|
||||
ret[i].name = b.params[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -1296,13 +1285,13 @@ func (b *binaryBuiltin) Name() ast.Identifier {
|
||||
type ternaryBuiltinFunc func(*interpreter, traceElement, value, value, value) (value, error)
|
||||
|
||||
type ternaryBuiltin struct {
|
||||
name ast.Identifier
|
||||
function ternaryBuiltinFunc
|
||||
parameters ast.Identifiers
|
||||
name ast.Identifier
|
||||
function ternaryBuiltinFunc
|
||||
params ast.Identifiers
|
||||
}
|
||||
|
||||
func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
flatArgs := flattenArgs(args, b.Parameters(), []value{})
|
||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||
builtinTrace := getBuiltinTrace(trace, b.name)
|
||||
x, err := flatArgs[0].getValue(i, trace)
|
||||
if err != nil {
|
||||
@ -1319,10 +1308,10 @@ func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace trac
|
||||
return b.function(i, builtinTrace, x, y, z)
|
||||
}
|
||||
|
||||
func (b *ternaryBuiltin) Parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.parameters))
|
||||
func (b *ternaryBuiltin) parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.params))
|
||||
for i := range ret {
|
||||
ret[i].name = b.parameters[i]
|
||||
ret[i].name = b.params[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -1345,16 +1334,16 @@ type generalBuiltinParameter struct {
|
||||
// have optional parameters. The optional ones have non-nil defaultValues
|
||||
// at the same index.
|
||||
type generalBuiltin struct {
|
||||
name ast.Identifier
|
||||
parameters []generalBuiltinParameter
|
||||
function generalBuiltinFunc
|
||||
name ast.Identifier
|
||||
params []generalBuiltinParameter
|
||||
function generalBuiltinFunc
|
||||
}
|
||||
|
||||
func (b *generalBuiltin) Parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.parameters))
|
||||
func (b *generalBuiltin) parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(b.params))
|
||||
for i := range ret {
|
||||
ret[i].name = b.parameters[i].name
|
||||
if b.parameters[i].defaultValue != nil {
|
||||
ret[i].name = b.params[i].name
|
||||
if b.params[i].defaultValue != nil {
|
||||
// This is not actually used because the defaultValue is used instead.
|
||||
// The only reason we don't leave it nil is because the checkArguments
|
||||
// function uses the non-nil status to indicate that the parameter
|
||||
@ -1366,9 +1355,9 @@ func (b *generalBuiltin) Parameters() []namedParameter {
|
||||
}
|
||||
|
||||
func (b *generalBuiltin) defaultValues() []value {
|
||||
ret := make([]value, len(b.parameters))
|
||||
ret := make([]value, len(b.params))
|
||||
for i := range ret {
|
||||
ret[i] = b.parameters[i].defaultValue
|
||||
ret[i] = b.params[i].defaultValue
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -1378,7 +1367,7 @@ func (b *generalBuiltin) Name() ast.Identifier {
|
||||
}
|
||||
|
||||
func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
flatArgs := flattenArgs(args, b.Parameters(), b.defaultValues())
|
||||
flatArgs := flattenArgs(args, b.parameters(), b.defaultValues())
|
||||
builtinTrace := getBuiltinTrace(trace, b.name)
|
||||
values := make([]value, len(flatArgs))
|
||||
for j := 0; j < len(values); j++ {
|
||||
@ -1393,38 +1382,38 @@ func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace trac
|
||||
|
||||
// End of builtin utils
|
||||
|
||||
var builtinID = &unaryBuiltin{name: "id", function: builtinIdentity, parameters: ast.Identifiers{"x"}}
|
||||
var builtinID = &unaryBuiltin{name: "id", function: builtinIdentity, params: ast.Identifiers{"x"}}
|
||||
var functionID = &valueFunction{ec: builtinID}
|
||||
|
||||
var bopBuiltins = []*binaryBuiltin{
|
||||
// Note that % and `in` are desugared instead of being handled here
|
||||
ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopDiv: &binaryBuiltin{name: "operator/", function: builtinDiv, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopDiv: &binaryBuiltin{name: "operator/", function: builtinDiv, params: ast.Identifiers{"x", "y"}},
|
||||
|
||||
ast.BopPlus: &binaryBuiltin{name: "operator+", function: builtinPlus, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopMinus: &binaryBuiltin{name: "operator-", function: builtinMinus, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopPlus: &binaryBuiltin{name: "operator+", function: builtinPlus, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopMinus: &binaryBuiltin{name: "operator-", function: builtinMinus, params: ast.Identifiers{"x", "y"}},
|
||||
|
||||
ast.BopShiftL: &binaryBuiltin{name: "operator<<", function: builtinShiftL, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopShiftR: &binaryBuiltin{name: "operator>>", function: builtinShiftR, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopShiftL: &binaryBuiltin{name: "operator<<", function: builtinShiftL, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopShiftR: &binaryBuiltin{name: "operator>>", function: builtinShiftR, params: ast.Identifiers{"x", "y"}},
|
||||
|
||||
ast.BopGreater: &binaryBuiltin{name: "operator>", function: builtinGreater, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopLessEq: &binaryBuiltin{name: "operator<=", function: builtinLessEq, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopGreater: &binaryBuiltin{name: "operator>", function: builtinGreater, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopLessEq: &binaryBuiltin{name: "operator<=", function: builtinLessEq, params: ast.Identifiers{"x", "y"}},
|
||||
|
||||
ast.BopManifestEqual: &binaryBuiltin{name: "operator==", function: builtinEquals, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopManifestUnequal: &binaryBuiltin{name: "operator!=", function: builtinNotEquals, parameters: ast.Identifiers{"x", "y"}}, // Special case
|
||||
ast.BopManifestEqual: &binaryBuiltin{name: "operator==", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopManifestUnequal: &binaryBuiltin{name: "operator!=", function: builtinNotEquals, params: ast.Identifiers{"x", "y"}}, // Special case
|
||||
|
||||
ast.BopBitwiseAnd: &binaryBuiltin{name: "operator&", function: builtinBitwiseAnd, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, parameters: ast.Identifiers{"x", "y"}},
|
||||
ast.BopBitwiseAnd: &binaryBuiltin{name: "operator&", function: builtinBitwiseAnd, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, params: ast.Identifiers{"x", "y"}},
|
||||
ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, params: ast.Identifiers{"x", "y"}},
|
||||
}
|
||||
|
||||
var uopBuiltins = []*unaryBuiltin{
|
||||
ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, parameters: ast.Identifiers{"x"}},
|
||||
ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, parameters: ast.Identifiers{"x"}},
|
||||
ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, parameters: ast.Identifiers{"x"}},
|
||||
ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, parameters: ast.Identifiers{"x"}},
|
||||
ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, params: ast.Identifiers{"x"}},
|
||||
ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, params: ast.Identifiers{"x"}},
|
||||
ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, params: ast.Identifiers{"x"}},
|
||||
ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, params: ast.Identifiers{"x"}},
|
||||
}
|
||||
|
||||
func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
|
||||
@ -1437,51 +1426,51 @@ func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
|
||||
|
||||
var funcBuiltins = buildBuiltinMap([]builtin{
|
||||
builtinID,
|
||||
&unaryBuiltin{name: "extVar", function: builtinExtVar, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "length", function: builtinLength, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "toString", function: builtinToString, parameters: ast.Identifiers{"a"}},
|
||||
&binaryBuiltin{name: "trace", function: builtinTrace, parameters: ast.Identifiers{"str", "rest"}},
|
||||
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, parameters: ast.Identifiers{"sz", "func"}},
|
||||
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, parameters: ast.Identifiers{"func", "arr"}},
|
||||
&binaryBuiltin{name: "join", function: builtinJoin, parameters: ast.Identifiers{"sep", "arr"}},
|
||||
&unaryBuiltin{name: "reverse", function: builtinReverse, parameters: ast.Identifiers{"arr"}},
|
||||
&binaryBuiltin{name: "filter", function: builtinFilter, parameters: ast.Identifiers{"func", "arr"}},
|
||||
&binaryBuiltin{name: "range", function: builtinRange, parameters: ast.Identifiers{"from", "to"}},
|
||||
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, parameters: ast.Identifiers{"x", "y"}},
|
||||
&binaryBuiltin{name: "equals", function: builtinEquals, parameters: ast.Identifiers{"x", "y"}},
|
||||
&binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, parameters: ast.Identifiers{"obj", "hidden"}},
|
||||
&ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, parameters: ast.Identifiers{"obj", "fname", "hidden"}},
|
||||
&unaryBuiltin{name: "type", function: builtinType, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "char", function: builtinChar, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "codepoint", function: builtinCodepoint, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "ceil", function: builtinCeil, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "floor", function: builtinFloor, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "sqrt", function: builtinSqrt, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "sin", function: builtinSin, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "cos", function: builtinCos, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "tan", function: builtinTan, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "asin", function: builtinAsin, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "acos", function: builtinAcos, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "atan", function: builtinAtan, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "log", function: builtinLog, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "exp", function: builtinExp, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "mantissa", function: builtinMantissa, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "exponent", function: builtinExponent, parameters: ast.Identifiers{"x"}},
|
||||
&binaryBuiltin{name: "pow", function: builtinPow, parameters: ast.Identifiers{"base", "exp"}},
|
||||
&binaryBuiltin{name: "modulo", function: builtinModulo, parameters: ast.Identifiers{"x", "y"}},
|
||||
&unaryBuiltin{name: "md5", function: builtinMd5, parameters: ast.Identifiers{"x"}},
|
||||
&ternaryBuiltin{name: "substr", function: builtinSubstr, parameters: ast.Identifiers{"str", "from", "len"}},
|
||||
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, parameters: ast.Identifiers{"str", "c", "maxsplits"}},
|
||||
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, parameters: ast.Identifiers{"str", "from", "to"}},
|
||||
&unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, parameters: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, parameters: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "parseJson", function: builtinParseJSON, parameters: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "base64", function: builtinBase64, parameters: ast.Identifiers{"input"}},
|
||||
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, parameters: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, parameters: ast.Identifiers{"arr"}},
|
||||
&generalBuiltin{name: "sort", function: builtinSort, parameters: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
||||
&unaryBuiltin{name: "native", function: builtinNative, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "extVar", function: builtinExtVar, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "length", function: builtinLength, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "toString", function: builtinToString, params: ast.Identifiers{"a"}},
|
||||
&binaryBuiltin{name: "trace", function: builtinTrace, params: ast.Identifiers{"str", "rest"}},
|
||||
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, params: ast.Identifiers{"sz", "func"}},
|
||||
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, params: ast.Identifiers{"func", "arr"}},
|
||||
&binaryBuiltin{name: "join", function: builtinJoin, params: ast.Identifiers{"sep", "arr"}},
|
||||
&unaryBuiltin{name: "reverse", function: builtinReverse, params: ast.Identifiers{"arr"}},
|
||||
&binaryBuiltin{name: "filter", function: builtinFilter, params: ast.Identifiers{"func", "arr"}},
|
||||
&binaryBuiltin{name: "range", function: builtinRange, params: ast.Identifiers{"from", "to"}},
|
||||
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, params: ast.Identifiers{"x", "y"}},
|
||||
&binaryBuiltin{name: "equals", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
|
||||
&binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, params: ast.Identifiers{"obj", "hidden"}},
|
||||
&ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, params: ast.Identifiers{"obj", "fname", "hidden"}},
|
||||
&unaryBuiltin{name: "type", function: builtinType, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "char", function: builtinChar, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "codepoint", function: builtinCodepoint, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "ceil", function: builtinCeil, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "floor", function: builtinFloor, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "sqrt", function: builtinSqrt, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "sin", function: builtinSin, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "cos", function: builtinCos, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "tan", function: builtinTan, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "asin", function: builtinAsin, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "acos", function: builtinAcos, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "atan", function: builtinAtan, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "log", function: builtinLog, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "exp", function: builtinExp, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "mantissa", function: builtinMantissa, params: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "exponent", function: builtinExponent, params: ast.Identifiers{"x"}},
|
||||
&binaryBuiltin{name: "pow", function: builtinPow, params: ast.Identifiers{"base", "exp"}},
|
||||
&binaryBuiltin{name: "modulo", function: builtinModulo, params: ast.Identifiers{"x", "y"}},
|
||||
&unaryBuiltin{name: "md5", function: builtinMd5, params: ast.Identifiers{"x"}},
|
||||
&ternaryBuiltin{name: "substr", function: builtinSubstr, params: ast.Identifiers{"str", "from", "len"}},
|
||||
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, params: ast.Identifiers{"str", "c", "maxsplits"}},
|
||||
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, params: ast.Identifiers{"str", "from", "to"}},
|
||||
&unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, params: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, params: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "parseJson", function: builtinParseJSON, params: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "base64", function: builtinBase64, params: ast.Identifiers{"input"}},
|
||||
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}},
|
||||
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}},
|
||||
&generalBuiltin{name: "sort", function: builtinSort, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
||||
&unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}},
|
||||
|
||||
// internal
|
||||
&unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, parameters: ast.Identifiers{"x"}},
|
||||
&unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, params: ast.Identifiers{"x"}},
|
||||
})
|
||||
|
@ -8,18 +8,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var jsonnetPath string
|
||||
var outputPassthru bool
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&jsonnetPath, "jsonnetPath", "./jsonnet", "Path to jsonnet binary")
|
||||
flag.BoolVar(&outputPassthru, "outputPassthru", false, "Pass stdout/err from jsonnet")
|
||||
}
|
||||
var (
|
||||
jsonnetPath = flag.String("jsonnetPath", "./jsonnet", "Path to jsonnet binary")
|
||||
outputPassthru = flag.Bool("outputPassthru", false, "Pass stdout/err from jsonnet")
|
||||
)
|
||||
|
||||
func RunBenchmark(b *testing.B, name string) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
cmd := exec.Command(jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
|
||||
if outputPassthru {
|
||||
cmd := exec.Command(*jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
|
||||
if *outputPassthru {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
|
||||
id, err := handles.make(newVM)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
|
||||
//export jsonnet_destroy
|
||||
func jsonnet_destroy(vmRef *C.struct_JsonnetVm) {
|
||||
if err := handles.free(uint32(vmRef.id)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -124,14 +124,14 @@ func getVM(vmRef *C.struct_JsonnetVm) *vm {
|
||||
ref, err := handles.get(uint32(vmRef.id))
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
v, ok := ref.(*vm)
|
||||
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "provided handle has a different type")
|
||||
fmt.Fprintln(os.Stderr, "provided handle has a different type")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -413,7 +413,7 @@ func jsonnet_json_destroy(vmRef *C.struct_JsonnetVm, v *C.struct_JsonnetJsonValu
|
||||
}
|
||||
|
||||
if err := handles.free(uint32(v.id)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -424,7 +424,7 @@ func createJSONValue(vmRef *C.struct_JsonnetVm, val interface{}) *C.struct_Jsonn
|
||||
id, err := handles.make(&jsonValue{val: val})
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -435,7 +435,7 @@ func getJSONValue(jsonRef *C.struct_JsonnetJsonValue) *jsonValue {
|
||||
ref, err := handles.get(uint32(jsonRef.id))
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,14 @@ func main() {
|
||||
ast := dump.Sdump(node)
|
||||
|
||||
dst := os.Stdout
|
||||
dst.WriteString(header)
|
||||
dst.WriteString(ast)
|
||||
_, err = dst.WriteString(header)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = dst.WriteString(ast)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var header = `
|
||||
|
@ -341,7 +341,7 @@ func readInput(config config, filename *string) (input string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func writeMultiOutputFiles(output map[string]string, outputDir, outputFile string, createDirs bool) error {
|
||||
func writeMultiOutputFiles(output map[string]string, outputDir, outputFile string, createDirs bool) (err error) {
|
||||
// If multiple file output is used, then iterate over each string from
|
||||
// the sequence of strings returned by jsonnet_evaluate_snippet_multi,
|
||||
// construct pairs of filename and content, and write each output file.
|
||||
@ -351,12 +351,15 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
|
||||
if outputFile == "" {
|
||||
manifest = os.Stdout
|
||||
} else {
|
||||
var err error
|
||||
manifest, err = os.Create(outputFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer manifest.Close()
|
||||
defer func() {
|
||||
if ferr := manifest.Close(); err != nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Iterate through the map in order.
|
||||
@ -401,7 +404,11 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if ferr := f.Close(); err != nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = f.WriteString(newContent)
|
||||
if err != nil {
|
||||
@ -413,18 +420,21 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
|
||||
}
|
||||
|
||||
// writeOutputStream writes the output as a YAML stream.
|
||||
func writeOutputStream(output []string, outputFile string) error {
|
||||
func writeOutputStream(output []string, outputFile string) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if outputFile == "" {
|
||||
f = os.Stdout
|
||||
} else {
|
||||
var err error
|
||||
f, err = os.Create(outputFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if ferr := f.Close(); err != nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, doc := range output {
|
||||
@ -448,7 +458,7 @@ func writeOutputStream(output []string, outputFile string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeOutputFile(output string, outputFile string, createDirs bool) error {
|
||||
func writeOutputFile(output string, outputFile string, createDirs bool) (err error) {
|
||||
if outputFile == "" {
|
||||
fmt.Print(output)
|
||||
return nil
|
||||
@ -460,11 +470,15 @@ func writeOutputFile(output string, outputFile string, createDirs bool) error {
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Create(outputFile)
|
||||
if err != nil {
|
||||
f, createErr := os.Create(outputFile)
|
||||
if createErr != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if ferr := f.Close(); err != nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = f.WriteString(output)
|
||||
return err
|
||||
@ -478,7 +492,10 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
err = pprof.StartCPUProfile(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
@ -519,7 +536,7 @@ func main() {
|
||||
|
||||
if len(config.inputFiles) != 1 {
|
||||
// Should already have been caught by processArgs.
|
||||
panic(fmt.Sprintf("Internal error: expected a single input file."))
|
||||
panic("Internal error: expected a single input file.")
|
||||
}
|
||||
filename := config.inputFiles[0]
|
||||
input, err := readInput(config, &filename)
|
||||
@ -560,7 +577,11 @@ func main() {
|
||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
||||
log.Fatal("could not write memory profile: ", err)
|
||||
}
|
||||
f.Close()
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
log.Fatal("Failed to close the memprofile: ", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -105,7 +105,7 @@ func (ef *termErrorFormatter) showCode(buf *bytes.Buffer, loc ast.LocationRange)
|
||||
beginning := ast.LineBeginning(&loc)
|
||||
ending := ast.LineEnding(&loc)
|
||||
fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(beginning))
|
||||
errFprintf(buf, "%v", ef.sp.GetSnippet(loc))
|
||||
errFprintf(buf, "%v", ef.sp.GetSnippet(loc)) //nolint:errcheck
|
||||
fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(ending))
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var packageNameStripperRegexp = regexp.MustCompile("\\b[a-zA-Z_]+[a-zA-Z_0-9]+\\.")
|
||||
var packageNameStripperRegexp = regexp.MustCompile(`\b[a-zA-Z_]+[a-zA-Z_0-9]+\.`)
|
||||
|
||||
// Options represents configuration option
|
||||
type Options struct {
|
||||
@ -59,16 +59,22 @@ type dumpState struct {
|
||||
reusedPointers []uintptr
|
||||
primitivePointers []uintptr
|
||||
|
||||
currentPointerName string
|
||||
homePackageRegexp *regexp.Regexp
|
||||
homePackageRegexp *regexp.Regexp
|
||||
}
|
||||
|
||||
func mustWrite(w io.Writer, data []byte) {
|
||||
_, err := w.Write(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *dumpState) indent() {
|
||||
s.w.Write(bytes.Repeat([]byte("\t"), s.depth))
|
||||
mustWrite(s.w, bytes.Repeat([]byte("\t"), s.depth))
|
||||
}
|
||||
|
||||
func (s *dumpState) newline() {
|
||||
s.w.Write([]byte("\n"))
|
||||
mustWrite(s.w, []byte("\n"))
|
||||
}
|
||||
|
||||
func (s *dumpState) dumpType(v reflect.Value) {
|
||||
@ -78,34 +84,34 @@ func (s *dumpState) dumpType(v reflect.Value) {
|
||||
} else if s.homePackageRegexp != nil {
|
||||
typeName = s.homePackageRegexp.ReplaceAllLiteralString(typeName, "")
|
||||
}
|
||||
s.w.Write([]byte(typeName))
|
||||
mustWrite(s.w, []byte(typeName))
|
||||
}
|
||||
|
||||
func (s *dumpState) dumpSlice(v reflect.Value) {
|
||||
s.dumpType(v)
|
||||
numEntries := v.Len()
|
||||
if numEntries == 0 {
|
||||
s.w.Write([]byte("{}"))
|
||||
mustWrite(s.w, []byte("{}"))
|
||||
return
|
||||
}
|
||||
s.w.Write([]byte("{"))
|
||||
mustWrite(s.w, []byte("{"))
|
||||
s.newline()
|
||||
s.depth++
|
||||
for i := 0; i < numEntries; i++ {
|
||||
s.indent()
|
||||
s.dumpVal(v.Index(i))
|
||||
s.w.Write([]byte(","))
|
||||
mustWrite(s.w, []byte(","))
|
||||
s.newline()
|
||||
}
|
||||
s.depth--
|
||||
s.indent()
|
||||
s.w.Write([]byte("}"))
|
||||
mustWrite(s.w, []byte("}"))
|
||||
}
|
||||
|
||||
func (s *dumpState) dumpStruct(v reflect.Value) {
|
||||
dumpPreamble := func() {
|
||||
s.dumpType(v)
|
||||
s.w.Write([]byte("{"))
|
||||
mustWrite(s.w, []byte("{"))
|
||||
s.newline()
|
||||
s.depth++
|
||||
}
|
||||
@ -122,26 +128,26 @@ func (s *dumpState) dumpStruct(v reflect.Value) {
|
||||
preambleDumped = true
|
||||
}
|
||||
s.indent()
|
||||
s.w.Write([]byte(vtf.Name))
|
||||
s.w.Write([]byte(": "))
|
||||
mustWrite(s.w, []byte(vtf.Name))
|
||||
mustWrite(s.w, []byte(": "))
|
||||
s.dumpVal(v.Field(i))
|
||||
s.w.Write([]byte(","))
|
||||
mustWrite(s.w, []byte(","))
|
||||
s.newline()
|
||||
}
|
||||
if preambleDumped {
|
||||
s.depth--
|
||||
s.indent()
|
||||
s.w.Write([]byte("}"))
|
||||
mustWrite(s.w, []byte("}"))
|
||||
} else {
|
||||
// There were no fields dumped
|
||||
s.dumpType(v)
|
||||
s.w.Write([]byte("{}"))
|
||||
mustWrite(s.w, []byte("{}"))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *dumpState) dumpMap(v reflect.Value) {
|
||||
s.dumpType(v)
|
||||
s.w.Write([]byte("{"))
|
||||
mustWrite(s.w, []byte("{"))
|
||||
s.newline()
|
||||
s.depth++
|
||||
keys := v.MapKeys()
|
||||
@ -149,14 +155,14 @@ func (s *dumpState) dumpMap(v reflect.Value) {
|
||||
for _, key := range keys {
|
||||
s.indent()
|
||||
s.dumpVal(key)
|
||||
s.w.Write([]byte(": "))
|
||||
mustWrite(s.w, []byte(": "))
|
||||
s.dumpVal(v.MapIndex(key))
|
||||
s.w.Write([]byte(","))
|
||||
mustWrite(s.w, []byte(","))
|
||||
s.newline()
|
||||
}
|
||||
s.depth--
|
||||
s.indent()
|
||||
s.w.Write([]byte("}"))
|
||||
mustWrite(s.w, []byte("}"))
|
||||
}
|
||||
|
||||
func (s *dumpState) dump(value interface{}) {
|
||||
@ -164,7 +170,7 @@ func (s *dumpState) dump(value interface{}) {
|
||||
if s.config.VariableDescription != "" {
|
||||
fmt.Fprintf(s.w, "\n// %s\n", s.config.VariableDescription)
|
||||
}
|
||||
s.w.Write([]byte("var " + s.config.VariableName + " = "))
|
||||
mustWrite(s.w, []byte("var "+s.config.VariableName+" = "))
|
||||
}
|
||||
|
||||
if value == nil {
|
||||
@ -194,11 +200,11 @@ func (s *dumpState) dump(value interface{}) {
|
||||
s.dumpVal(v)
|
||||
s.w = oldWriter
|
||||
if buf.Len() > 100 {
|
||||
s.w.Write([]byte("_" + s.config.VariableName))
|
||||
mustWrite(s.w, []byte("_"+s.config.VariableName))
|
||||
s.newline()
|
||||
s.w.Write([]byte("var _" + s.config.VariableName + " = "))
|
||||
mustWrite(s.w, []byte("var _"+s.config.VariableName+" = "))
|
||||
}
|
||||
s.w.Write(buf.Bytes())
|
||||
mustWrite(s.w, buf.Bytes())
|
||||
}
|
||||
s.newline()
|
||||
}
|
||||
@ -206,7 +212,7 @@ func (s *dumpState) dump(value interface{}) {
|
||||
func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName string) {
|
||||
v := deInterface(value)
|
||||
|
||||
s.w.Write([]byte("var " + pointerName + "Var" + " = "))
|
||||
mustWrite(s.w, []byte("var "+pointerName+"Var"+" = "))
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
printBool(s.w, v.Bool())
|
||||
@ -244,11 +250,11 @@ func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName strin
|
||||
printComplex(s.w, v.Complex(), 64)
|
||||
|
||||
case reflect.String:
|
||||
s.w.Write([]byte(strconv.Quote(v.String())))
|
||||
mustWrite(s.w, []byte(strconv.Quote(v.String())))
|
||||
}
|
||||
|
||||
s.newline()
|
||||
s.w.Write([]byte("var " + pointerName + " = &" + pointerName + "Var"))
|
||||
mustWrite(s.w, []byte("var "+pointerName+" = &"+pointerName+"Var"))
|
||||
s.newline()
|
||||
}
|
||||
|
||||
@ -263,7 +269,7 @@ func (s *dumpState) dumpPrimitivePointerVal(value reflect.Value) {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
s.w.Write([]byte("<invalid>"))
|
||||
mustWrite(s.w, []byte("<invalid>"))
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
@ -310,7 +316,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
s.w.Write([]byte("<invalid>"))
|
||||
mustWrite(s.w, []byte("<invalid>"))
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
@ -338,7 +344,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
|
||||
case reflect.Ptr:
|
||||
pointerName, isReused, isPrimitive, isFirstVisit := s.nameForPointer(v), s.isReusedPointer(v), s.isPrimitivePointer(v), s.visitPointerAndCheckIfFirstTime(v)
|
||||
if isReused && !isPrimitive && isFirstVisit {
|
||||
s.w.Write([]byte("var " + pointerName + " = &"))
|
||||
mustWrite(s.w, []byte("var "+pointerName+" = &"))
|
||||
s.dumpVal(v.Elem())
|
||||
s.newline()
|
||||
} else {
|
||||
@ -349,7 +355,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
|
||||
|
||||
func (s *dumpState) dumpVal(value reflect.Value) {
|
||||
if value.Kind() == reflect.Ptr && value.IsNil() {
|
||||
s.w.Write([]byte("nil"))
|
||||
mustWrite(s.w, []byte("nil"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -359,7 +365,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
s.w.Write([]byte("<invalid>"))
|
||||
mustWrite(s.w, []byte("<invalid>"))
|
||||
|
||||
case reflect.Bool:
|
||||
printBool(s.w, v.Bool())
|
||||
@ -397,7 +403,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
|
||||
printComplex(s.w, v.Complex(), 64)
|
||||
|
||||
case reflect.String:
|
||||
s.w.Write([]byte(strconv.Quote(v.String())))
|
||||
mustWrite(s.w, []byte(strconv.Quote(v.String())))
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
@ -419,9 +425,9 @@ func (s *dumpState) dumpVal(value reflect.Value) {
|
||||
case reflect.Ptr:
|
||||
pointerName, isPrimitive, isReused := s.nameForPointer(v), s.isPrimitivePointer(v), s.isReusedPointer(v)
|
||||
if isPrimitive || isReused {
|
||||
s.w.Write([]byte(pointerName))
|
||||
mustWrite(s.w, []byte(pointerName))
|
||||
} else {
|
||||
s.w.Write([]byte("&"))
|
||||
mustWrite(s.w, []byte("&"))
|
||||
s.dumpVal(v.Elem())
|
||||
}
|
||||
|
||||
@ -440,19 +446,6 @@ func (s *dumpState) dumpVal(value reflect.Value) {
|
||||
}
|
||||
}
|
||||
|
||||
// call to signal that the pointer is being visited, returns true if this is the
|
||||
// first visit to that pointer. Used to detect when to output the entire contents
|
||||
// behind a pointer (the first time), and when to just emit a name (all other times)
|
||||
func (s *dumpState) visitPointerAndCheckIfItIsTheFirstTime(ptr uintptr) bool {
|
||||
for _, addr := range s.visitedPointers {
|
||||
if addr == ptr {
|
||||
return false
|
||||
}
|
||||
}
|
||||
s.visitedPointers = append(s.visitedPointers, ptr)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *dumpState) nameForPointer(v reflect.Value) string {
|
||||
if isPointerValue(v) {
|
||||
ptr := v.Pointer()
|
||||
|
@ -25,42 +25,42 @@ import (
|
||||
)
|
||||
|
||||
func printBool(w io.Writer, value bool) {
|
||||
w.Write([]byte(strconv.FormatBool(value)))
|
||||
mustWrite(w, []byte(strconv.FormatBool(value)))
|
||||
}
|
||||
|
||||
func printInt(w io.Writer, val reflect.Value, stripPackageName bool) {
|
||||
typeName := fmt.Sprintf("%s", val.Type())
|
||||
typeName := val.Type().String()
|
||||
if stripPackageName && strings.HasPrefix(typeName, "ast.") {
|
||||
typeName = typeName[4:]
|
||||
}
|
||||
w.Write([]byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatInt(val.Int(), 10))))
|
||||
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatInt(val.Int(), 10))))
|
||||
}
|
||||
|
||||
func printUint(w io.Writer, val reflect.Value) {
|
||||
typeName := fmt.Sprintf("%s", val.Type())
|
||||
w.Write([]byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10))))
|
||||
typeName := val.Type().String()
|
||||
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10))))
|
||||
}
|
||||
|
||||
func printFloat(w io.Writer, val float64, precision int, floatType string) {
|
||||
w.Write([]byte(fmt.Sprintf("%s(%s)", floatType, strconv.FormatFloat(val, 'g', -1, precision))))
|
||||
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", floatType, strconv.FormatFloat(val, 'g', -1, precision))))
|
||||
}
|
||||
|
||||
func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||
w.Write([]byte("complex"))
|
||||
w.Write([]byte(fmt.Sprintf("%d", floatPrecision*2)))
|
||||
mustWrite(w, []byte("complex"))
|
||||
mustWrite(w, []byte(fmt.Sprintf("%d", floatPrecision*2)))
|
||||
r := real(c)
|
||||
w.Write([]byte("("))
|
||||
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
||||
mustWrite(w, []byte("("))
|
||||
mustWrite(w, []byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
||||
i := imag(c)
|
||||
if i >= 0 {
|
||||
w.Write([]byte("+"))
|
||||
mustWrite(w, []byte("+"))
|
||||
}
|
||||
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
||||
w.Write([]byte("i)"))
|
||||
mustWrite(w, []byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
||||
mustWrite(w, []byte("i)"))
|
||||
}
|
||||
|
||||
func printNil(w io.Writer) {
|
||||
w.Write([]byte("nil"))
|
||||
mustWrite(w, []byte("nil"))
|
||||
}
|
||||
|
||||
// deInterface returns values inside of non-nil interfaces when possible.
|
||||
|
@ -412,16 +412,13 @@ func (l *lexer) lexWhitespace() (int, int) {
|
||||
switch r {
|
||||
case '\r':
|
||||
// Ignore.
|
||||
break
|
||||
|
||||
case '\n':
|
||||
indent = 0
|
||||
newLines++
|
||||
break
|
||||
|
||||
case ' ':
|
||||
indent++
|
||||
break
|
||||
|
||||
// This only works for \t at the beginning of lines, but we strip it everywhere else
|
||||
// anyway. The only case where this will cause a problem is spaces followed by \t
|
||||
@ -429,7 +426,6 @@ func (l *lexer) lexWhitespace() (int, int) {
|
||||
// is enabled it will be fixed later.
|
||||
case '\t':
|
||||
indent += 8
|
||||
break
|
||||
}
|
||||
}
|
||||
l.backup()
|
||||
@ -489,7 +485,7 @@ func (l *lexer) lexNumber() error {
|
||||
state := numBegin
|
||||
|
||||
outerLoop:
|
||||
for true {
|
||||
for {
|
||||
r := l.next()
|
||||
switch state {
|
||||
case numBegin:
|
||||
@ -654,6 +650,7 @@ func (l *lexer) lexSymbol() error {
|
||||
margin := l.pos.byteNo - l.pos.lineStart
|
||||
commentStartLoc := l.tokenStartLoc
|
||||
|
||||
//nolint:ineffassign,staticcheck
|
||||
r := l.next() // consume the initial '*'
|
||||
for r = l.next(); r != '*' || l.peek() != '/'; r = l.next() {
|
||||
if r == lexEOF {
|
||||
@ -687,9 +684,9 @@ func (l *lexer) lexSymbol() error {
|
||||
}
|
||||
}
|
||||
if allStar {
|
||||
for _, l := range lines {
|
||||
if l[0] == '*' {
|
||||
l = " " + l
|
||||
for i := range lines {
|
||||
if lines[i][0] == '*' {
|
||||
lines[i] = " " + lines[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -813,7 +810,7 @@ func Lex(fn string, input string) (Tokens, error) {
|
||||
l := makeLexer(fn, input)
|
||||
|
||||
var err error
|
||||
for true {
|
||||
for {
|
||||
newLines, indent := l.lexWhitespace()
|
||||
// If it's the end of the file, discard final whitespace.
|
||||
if l.peek() == lexEOF {
|
||||
@ -855,7 +852,8 @@ func Lex(fn string, input string) (Tokens, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// String literals
|
||||
// String literals
|
||||
|
||||
case '"':
|
||||
stringStartLoc := l.prevLocation()
|
||||
for r = l.next(); ; r = l.next() {
|
||||
@ -869,6 +867,7 @@ func Lex(fn string, input string) (Tokens, error) {
|
||||
break
|
||||
}
|
||||
if r == '\\' && l.peek() != lexEOF {
|
||||
//nolint:ineffassign,staticcheck
|
||||
r = l.next()
|
||||
}
|
||||
}
|
||||
@ -885,6 +884,7 @@ func Lex(fn string, input string) (Tokens, error) {
|
||||
break
|
||||
}
|
||||
if r == '\\' && l.peek() != lexEOF {
|
||||
//nolint:ineffassign,staticcheck
|
||||
r = l.next()
|
||||
}
|
||||
}
|
||||
|
@ -21,127 +21,10 @@ import (
|
||||
"github.com/google/go-jsonnet/ast"
|
||||
)
|
||||
|
||||
type lexTest struct {
|
||||
name string
|
||||
input string
|
||||
tokens Tokens
|
||||
errString string
|
||||
}
|
||||
|
||||
var (
|
||||
tEOF = token{kind: tokenEndOfFile}
|
||||
)
|
||||
|
||||
var lexTests = []lexTest{
|
||||
{
|
||||
"block string spaces",
|
||||
`|||
|
||||
test
|
||||
more
|
||||
|||
|
||||
foo
|
||||
|||`,
|
||||
Tokens{
|
||||
{
|
||||
kind: tokenStringBlock,
|
||||
data: "test\n more\n|||\n foo\n",
|
||||
stringBlockIndent: " ",
|
||||
stringBlockTermIndent: "",
|
||||
},
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"block string tabs",
|
||||
`|||
|
||||
test
|
||||
more
|
||||
|||
|
||||
foo
|
||||
|||`,
|
||||
Tokens{
|
||||
{
|
||||
kind: tokenStringBlock,
|
||||
data: "test\n more\n|||\n foo\n",
|
||||
stringBlockIndent: "\t",
|
||||
stringBlockTermIndent: "",
|
||||
},
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"block string mixed",
|
||||
`|||
|
||||
test
|
||||
more
|
||||
|||
|
||||
foo
|
||||
|||`,
|
||||
Tokens{
|
||||
{
|
||||
kind: tokenStringBlock,
|
||||
data: "test\n more\n|||\n foo\n",
|
||||
stringBlockIndent: "\t \t",
|
||||
stringBlockTermIndent: "",
|
||||
},
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"block string blanks",
|
||||
`|||
|
||||
|
||||
test
|
||||
|
||||
|
||||
more
|
||||
|||
|
||||
foo
|
||||
|||`,
|
||||
Tokens{
|
||||
{
|
||||
kind: tokenStringBlock,
|
||||
data: "\ntest\n\n\n more\n|||\n foo\n",
|
||||
stringBlockIndent: " ",
|
||||
stringBlockTermIndent: "",
|
||||
},
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"block string bad indent",
|
||||
`|||
|
||||
test
|
||||
foo
|
||||
|||`,
|
||||
Tokens{},
|
||||
"block string bad indent:1:1 Text block not terminated with |||",
|
||||
},
|
||||
{
|
||||
"block string eof",
|
||||
`|||
|
||||
test`,
|
||||
Tokens{},
|
||||
"block string eof:1:1 Unexpected EOF",
|
||||
},
|
||||
{
|
||||
"block string not term",
|
||||
`|||
|
||||
test
|
||||
`,
|
||||
Tokens{},
|
||||
"block string not term:1:1 Text block not terminated with |||",
|
||||
},
|
||||
{
|
||||
"block string no ws",
|
||||
`|||
|
||||
test
|
||||
|||`,
|
||||
Tokens{},
|
||||
"block string no ws:1:1 Text block's first line must start with whitespace",
|
||||
},
|
||||
}
|
||||
|
||||
func fodderEqual(f1 ast.Fodder, f2 ast.Fodder) bool {
|
||||
if len(f1) != len(f2) {
|
||||
return false
|
||||
|
@ -120,16 +120,6 @@ func (p *parser) doublePeek() *token {
|
||||
return &p.t[p.currT+1]
|
||||
}
|
||||
|
||||
// in some cases it's convenient to parse something as an expression, and later
|
||||
// decide that it should be just an identifer
|
||||
func astVarToIdentifier(node ast.Node) (ast.Fodder, *ast.Identifier, bool) {
|
||||
v, ok := node.(*ast.Var)
|
||||
if ok {
|
||||
return v.NodeBase.Fodder, &v.Id, true
|
||||
}
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
// parseArgument parses either <f1> id <f2> = expr or just expr.
|
||||
// It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr)
|
||||
// respectively.
|
||||
|
@ -167,7 +167,10 @@ func desugarFields(nodeBase ast.NodeBase, fields *ast.ObjectFields, objLevel int
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
desugarLocalBinds(locals, objLevel+1)
|
||||
err := desugarLocalBinds(locals, objLevel+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range desugaredFields {
|
||||
field := &(desugaredFields[i])
|
||||
if field.Name != nil {
|
||||
|
@ -205,14 +205,6 @@ func (s *callStack) getCurrentEnv(ast ast.Node) environment {
|
||||
)
|
||||
}
|
||||
|
||||
func (s *callStack) getTopEnv() environment {
|
||||
top := s.stack[len(s.stack)-1]
|
||||
if !top.isCall {
|
||||
panic("getTopEnv is allowed only for artifical nodes which are called in new environment")
|
||||
}
|
||||
return top.env
|
||||
}
|
||||
|
||||
// Build a binding frame containing specified variables.
|
||||
func (s *callStack) capture(freeVars ast.Identifiers) bindingFrame {
|
||||
env := make(bindingFrame)
|
||||
@ -482,7 +474,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) {
|
||||
// too large to fit in a double.
|
||||
num, err := strconv.ParseFloat(node.OriginalString, 64)
|
||||
if err != nil {
|
||||
return nil, i.Error(fmt.Sprintf("overflow"), trace)
|
||||
return nil, i.Error("overflow", trace)
|
||||
}
|
||||
return makeValueNumber(num), nil
|
||||
|
||||
@ -968,6 +960,7 @@ func (i *interpreter) getNumber(val value, trace traceElement) (*valueNumber, er
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateNumber(pv potentialValue, trace traceElement) (*valueNumber, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
@ -998,6 +991,7 @@ func (i *interpreter) evaluateInt(pv potentialValue, trace traceElement) (int, e
|
||||
return i.getInt(v, trace)
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
|
||||
num, err := i.getNumber(val, trace)
|
||||
if err != nil {
|
||||
@ -1010,6 +1004,7 @@ func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
|
||||
return intNum, nil
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateInt64(pv potentialValue, trace traceElement) (int64, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
@ -1027,6 +1022,7 @@ func (i *interpreter) getString(val value, trace traceElement) (valueString, err
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateString(pv potentialValue, trace traceElement) (valueString, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
@ -1044,6 +1040,7 @@ func (i *interpreter) getBoolean(val value, trace traceElement) (*valueBoolean,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateBoolean(pv potentialValue, trace traceElement) (*valueBoolean, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
@ -1061,6 +1058,7 @@ func (i *interpreter) getArray(val value, trace traceElement) (*valueArray, erro
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateArray(pv potentialValue, trace traceElement) (*valueArray, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
@ -1078,6 +1076,7 @@ func (i *interpreter) getFunction(val value, trace traceElement) (*valueFunction
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (i *interpreter) evaluateFunction(pv potentialValue, trace traceElement) (*valueFunction, error) {
|
||||
v, err := i.evaluatePV(pv, trace)
|
||||
if err != nil {
|
||||
|
@ -39,7 +39,10 @@ func main() {
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
inputFile.Close()
|
||||
err = inputFile.Close()
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
node, err := jsonnet.SnippetToAST(p, string(data))
|
||||
if err != nil {
|
||||
die(err)
|
||||
|
@ -17,7 +17,10 @@ type ErrorWriter struct {
|
||||
|
||||
func (e *ErrorWriter) writeError(err errors.StaticError) {
|
||||
e.ErrorsFound = true
|
||||
e.Writer.Write([]byte(err.Error() + "\n"))
|
||||
_, writeErr := e.Writer.Write([]byte(err.Error() + "\n"))
|
||||
if writeErr != nil {
|
||||
panic(writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
type variable struct {
|
||||
|
16
main_test.go
16
main_test.go
@ -398,7 +398,7 @@ func TestEval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func withinWorkingDirectory(t *testing.T, dir string) func() error {
|
||||
func withinWorkingDirectory(t *testing.T, dir string) func() {
|
||||
t.Helper()
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -407,8 +407,11 @@ func withinWorkingDirectory(t *testing.T, dir string) func() error {
|
||||
if err := os.Chdir(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return func() error {
|
||||
return os.Chdir(cwd)
|
||||
return func() {
|
||||
err := os.Chdir(cwd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +429,12 @@ func TestEvalUnusualFilenames(t *testing.T) {
|
||||
if dir, err = ioutil.TempDir("", "jsonnet"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
defer func() {
|
||||
err := os.RemoveAll(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
copySmallFile := func(t *testing.T, dst, src string) {
|
||||
|
6
testdata/std.sort4.golden
vendored
6
testdata/std.sort4.golden
vendored
@ -1,10 +1,10 @@
|
||||
RUNTIME ERROR: foo
|
||||
RUNTIME ERROR: Unexpected type array
|
||||
-------------------------------------------------
|
||||
testdata/std.sort4:1:15-26 thunk from <thunk from <thunk from <$>>>
|
||||
testdata/std.sort4:1:1-29 builtin function <sort>
|
||||
|
||||
std.sort([1, [error "foo"]])
|
||||
|
||||
-------------------------------------------------
|
||||
During manifestation
|
||||
During evaluation
|
||||
|
||||
|
||||
|
31
thunks.go
31
thunks.go
@ -36,19 +36,9 @@ func (rv *readyValue) evaluate(i *interpreter, trace traceElement, sb selfBindin
|
||||
return rv.content, nil
|
||||
}
|
||||
|
||||
func (rv *readyValue) aPotentialValue() {}
|
||||
|
||||
// potentialValues
|
||||
// -------------------------------------
|
||||
|
||||
// evaluable is something that can be evaluated and the result is always the same
|
||||
// It may require computation every time evaluation is requested (in contrast with
|
||||
// potentialValue which guarantees that computation happens at most once).
|
||||
type evaluable interface {
|
||||
// fromWhere keeps the information from where the evaluation was requested.
|
||||
getValue(i *interpreter, fromWhere traceElement) (value, error)
|
||||
}
|
||||
|
||||
// cachedThunk is a wrapper that caches the value of a potentialValue after
|
||||
// the first evaluation.
|
||||
// Note: All potentialValues are required to provide the same value every time,
|
||||
@ -110,8 +100,7 @@ type bindingsUnboundField struct {
|
||||
}
|
||||
|
||||
func (f *bindingsUnboundField) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) {
|
||||
var upValues bindingFrame
|
||||
upValues = make(bindingFrame)
|
||||
upValues := make(bindingFrame)
|
||||
for variable, pvalue := range origBindings {
|
||||
upValues[variable] = pvalue
|
||||
}
|
||||
@ -164,7 +153,7 @@ func forceThunks(i *interpreter, trace traceElement, args *bindingFrame) error {
|
||||
|
||||
func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
argThunks := make(bindingFrame)
|
||||
parameters := closure.Parameters()
|
||||
parameters := closure.parameters()
|
||||
for i, arg := range arguments.positional {
|
||||
argThunks[parameters[i].name] = arg
|
||||
}
|
||||
@ -199,7 +188,7 @@ func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace
|
||||
return i.EvalInCleanEnv(trace, &calledEnvironment, closure.function.Body, arguments.tailstrict)
|
||||
}
|
||||
|
||||
func (closure *closure) Parameters() []namedParameter {
|
||||
func (closure *closure) parameters() []namedParameter {
|
||||
return closure.params
|
||||
|
||||
}
|
||||
@ -232,7 +221,7 @@ type NativeFunction struct {
|
||||
|
||||
// evalCall evaluates a call to a NativeFunction and returns the result.
|
||||
func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) {
|
||||
flatArgs := flattenArgs(arguments, native.Parameters(), []value{})
|
||||
flatArgs := flattenArgs(arguments, native.parameters(), []value{})
|
||||
nativeArgs := make([]interface{}, 0, len(flatArgs))
|
||||
for _, arg := range flatArgs {
|
||||
v, err := i.evaluatePV(arg, trace)
|
||||
@ -253,20 +242,10 @@ func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter,
|
||||
}
|
||||
|
||||
// Parameters returns a NativeFunction's parameters.
|
||||
func (native *NativeFunction) Parameters() []namedParameter {
|
||||
func (native *NativeFunction) parameters() []namedParameter {
|
||||
ret := make([]namedParameter, len(native.Params))
|
||||
for i := range ret {
|
||||
ret[i].name = native.Params[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
type defaultArgument struct {
|
||||
body ast.Node
|
||||
}
|
||||
|
||||
func (da *defaultArgument) inEnv(env *environment) potentialValue {
|
||||
return &cachedThunk{env: env, body: da.body}
|
||||
}
|
||||
|
31
value.go
31
value.go
@ -313,9 +313,7 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
|
||||
arrayElems = elements
|
||||
} else {
|
||||
arrayElems = make([]*cachedThunk, len(elements))
|
||||
for i := range elements {
|
||||
arrayElems[i] = elements[i]
|
||||
}
|
||||
copy(arrayElems, elements)
|
||||
}
|
||||
return &valueArray{
|
||||
elements: arrayElems,
|
||||
@ -324,12 +322,8 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
|
||||
|
||||
func concatArrays(a, b *valueArray) *valueArray {
|
||||
result := make([]*cachedThunk, 0, len(a.elements)+len(b.elements))
|
||||
for _, r := range a.elements {
|
||||
result = append(result, r)
|
||||
}
|
||||
for _, r := range b.elements {
|
||||
result = append(result, r)
|
||||
}
|
||||
result = append(result, a.elements...)
|
||||
result = append(result, b.elements...)
|
||||
return &valueArray{elements: result}
|
||||
}
|
||||
|
||||
@ -348,19 +342,19 @@ type valueFunction struct {
|
||||
// TODO(sbarzowski) better name?
|
||||
type evalCallable interface {
|
||||
evalCall(args callArguments, i *interpreter, trace traceElement) (value, error)
|
||||
Parameters() []namedParameter
|
||||
parameters() []namedParameter
|
||||
}
|
||||
|
||||
func (f *valueFunction) call(i *interpreter, trace traceElement, args callArguments) (value, error) {
|
||||
err := checkArguments(i, trace, args, f.Parameters())
|
||||
err := checkArguments(i, trace, args, f.parameters())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.ec.evalCall(args, i, trace)
|
||||
}
|
||||
|
||||
func (f *valueFunction) Parameters() []namedParameter {
|
||||
return f.ec.Parameters()
|
||||
func (f *valueFunction) parameters() []namedParameter {
|
||||
return f.ec.parameters()
|
||||
}
|
||||
|
||||
func checkArguments(i *interpreter, trace traceElement, args callArguments, params []namedParameter) error {
|
||||
@ -406,22 +400,11 @@ func (f *valueFunction) getType() *valueType {
|
||||
return functionType
|
||||
}
|
||||
|
||||
// parameters represents required position and optional named parameters for a
|
||||
// function definition.
|
||||
type parameters struct {
|
||||
required ast.Identifiers
|
||||
optional []namedParameter
|
||||
}
|
||||
|
||||
type namedParameter struct {
|
||||
name ast.Identifier
|
||||
defaultArg ast.Node
|
||||
}
|
||||
|
||||
type potentialValueInEnv interface {
|
||||
inEnv(env *environment) *cachedThunk
|
||||
}
|
||||
|
||||
type callArguments struct {
|
||||
positional []*cachedThunk
|
||||
named []namedCallArgument
|
||||
|
Loading…
x
Reference in New Issue
Block a user