Make golangci-lint happy

Some of the suggestions are minor bug fixes (missing error handling).
This commit is contained in:
Stanisław Barzowski 2020-03-01 20:19:23 +01:00
parent 803ad646cb
commit 9ada769ce4
22 changed files with 290 additions and 426 deletions

View File

@ -429,7 +429,8 @@ type Index struct {
// 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 always empty. // When Id is being used, this is always empty.
RightBracketFodder Fodder 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]. // Slice represents an array slice a[begin:end:step].
@ -576,9 +577,10 @@ type ObjectField struct {
// 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 Fodder1 Fodder
Expr1 Node // Not in scope of the object 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 Id *Identifier
Fodder2 Fodder Fodder2 Fodder
OpFodder Fodder OpFodder Fodder
@ -676,7 +678,8 @@ type SuperIndex struct {
// 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
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. // InSuper represents the e in super construct.
@ -734,6 +737,7 @@ type Unary struct {
// Var represents variables. // Var represents variables.
type Var struct { type Var struct {
NodeBase NodeBase
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id Identifier Id Identifier
} }

View File

@ -87,7 +87,7 @@ func MakeFodderElement(kind FodderKind, blanks int, indent int, comment []string
panic(fmt.Sprintf("FodderInterstitial but comment == %v.", comment)) panic(fmt.Sprintf("FodderInterstitial but comment == %v.", comment))
} }
if kind == FodderParagraph && len(comment) == 0 { 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} return FodderElement{Kind: kind, Blanks: blanks, Indent: indent, Comment: comment}
} }

View File

@ -45,7 +45,10 @@ func (l *Location) String() string {
return fmt.Sprintf("%v:%v", l.Line, l.Column) 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 { if a.Line != b.Line {
return a.Line < b.Line return a.Line < b.Line
} }

View File

@ -182,7 +182,7 @@ func builtinLength(i *interpreter, trace traceElement, x value) (value, error) {
case valueString: case valueString:
num = x.length() num = x.length()
case *valueFunction: case *valueFunction:
for _, param := range x.Parameters() { for _, param := range x.parameters() {
if param.defaultArg == nil { if param.defaultArg == nil {
num++ num++
} }
@ -275,9 +275,7 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, elem := range returned.elements { elems = append(elems, returned.elements...)
elems = append(elems, elem)
}
} }
return makeValueArray(elems), nil return makeValueArray(elems), nil
} }
@ -295,13 +293,9 @@ func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueA
continue continue
case *valueArray: case *valueArray:
if !first { if !first {
for _, subElem := range sep.elements { result = append(result, sep.elements...)
result = append(result, subElem)
}
}
for _, subElem := range v.elements {
result = append(result, subElem)
} }
result = append(result, v.elements...)
default: default:
return nil, i.typeErrorSpecific(elemValue, &valueArray{}, trace) return nil, i.typeErrorSpecific(elemValue, &valueArray{}, trace)
} }
@ -435,14 +429,6 @@ func (d *sortData) Sort() (err error) {
return 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) { func builtinSort(i *interpreter, trace traceElement, arguments []value) (value, error) {
arrv := arguments[0] arrv := arguments[0]
keyFv := arguments[1] 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 return makeValueArray(data.thunks), nil
} }
@ -705,8 +694,8 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro
return nil, err return nil, err
} }
runes := []rune(vStr.getGoString()) str := vStr.getGoString()
for _, r := range runes { for _, r := range str {
n := int(r) n := int(r)
msg, ok := sanityCheck(n) msg, ok := sanityCheck(n)
if !ok { 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: case *valueArray:
vArr, err := i.getArray(input, trace) vArr, err := i.getArray(input, trace)
if err != nil { if err != nil {
@ -1227,9 +1216,9 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value)
type unaryBuiltinFunc func(*interpreter, traceElement, value) (value, error) type unaryBuiltinFunc func(*interpreter, traceElement, value) (value, error)
type unaryBuiltin struct { type unaryBuiltin struct {
name ast.Identifier name ast.Identifier
function unaryBuiltinFunc function unaryBuiltinFunc
parameters ast.Identifiers params ast.Identifiers
} }
func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement { 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) { 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) builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace) x, err := flatArgs[0].getValue(i, trace)
if err != nil { if err != nil {
@ -1247,10 +1236,10 @@ func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceE
return b.function(i, builtinTrace, x) return b.function(i, builtinTrace, x)
} }
func (b *unaryBuiltin) Parameters() []namedParameter { func (b *unaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters)) ret := make([]namedParameter, len(b.params))
for i := range ret { for i := range ret {
ret[i].name = b.parameters[i] ret[i].name = b.params[i]
} }
return ret return ret
} }
@ -1262,13 +1251,13 @@ func (b *unaryBuiltin) Name() ast.Identifier {
type binaryBuiltinFunc func(*interpreter, traceElement, value, value) (value, error) type binaryBuiltinFunc func(*interpreter, traceElement, value, value) (value, error)
type binaryBuiltin struct { type binaryBuiltin struct {
name ast.Identifier name ast.Identifier
function binaryBuiltinFunc function binaryBuiltinFunc
parameters ast.Identifiers params ast.Identifiers
} }
func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { 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) builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace) x, err := flatArgs[0].getValue(i, trace)
if err != nil { if err != nil {
@ -1281,10 +1270,10 @@ func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace trace
return b.function(i, builtinTrace, x, y) return b.function(i, builtinTrace, x, y)
} }
func (b *binaryBuiltin) Parameters() []namedParameter { func (b *binaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters)) ret := make([]namedParameter, len(b.params))
for i := range ret { for i := range ret {
ret[i].name = b.parameters[i] ret[i].name = b.params[i]
} }
return ret return ret
} }
@ -1296,13 +1285,13 @@ func (b *binaryBuiltin) Name() ast.Identifier {
type ternaryBuiltinFunc func(*interpreter, traceElement, value, value, value) (value, error) type ternaryBuiltinFunc func(*interpreter, traceElement, value, value, value) (value, error)
type ternaryBuiltin struct { type ternaryBuiltin struct {
name ast.Identifier name ast.Identifier
function ternaryBuiltinFunc function ternaryBuiltinFunc
parameters ast.Identifiers params ast.Identifiers
} }
func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { 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) builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace) x, err := flatArgs[0].getValue(i, trace)
if err != nil { 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) return b.function(i, builtinTrace, x, y, z)
} }
func (b *ternaryBuiltin) Parameters() []namedParameter { func (b *ternaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters)) ret := make([]namedParameter, len(b.params))
for i := range ret { for i := range ret {
ret[i].name = b.parameters[i] ret[i].name = b.params[i]
} }
return ret return ret
} }
@ -1345,16 +1334,16 @@ type generalBuiltinParameter struct {
// have optional parameters. The optional ones have non-nil defaultValues // have optional parameters. The optional ones have non-nil defaultValues
// at the same index. // at the same index.
type generalBuiltin struct { type generalBuiltin struct {
name ast.Identifier name ast.Identifier
parameters []generalBuiltinParameter params []generalBuiltinParameter
function generalBuiltinFunc function generalBuiltinFunc
} }
func (b *generalBuiltin) Parameters() []namedParameter { func (b *generalBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters)) ret := make([]namedParameter, len(b.params))
for i := range ret { for i := range ret {
ret[i].name = b.parameters[i].name ret[i].name = b.params[i].name
if b.parameters[i].defaultValue != nil { if b.params[i].defaultValue != nil {
// This is not actually used because the defaultValue is used instead. // This is not actually used because the defaultValue is used instead.
// The only reason we don't leave it nil is because the checkArguments // The only reason we don't leave it nil is because the checkArguments
// function uses the non-nil status to indicate that the parameter // 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 { func (b *generalBuiltin) defaultValues() []value {
ret := make([]value, len(b.parameters)) ret := make([]value, len(b.params))
for i := range ret { for i := range ret {
ret[i] = b.parameters[i].defaultValue ret[i] = b.params[i].defaultValue
} }
return ret return ret
} }
@ -1378,7 +1367,7 @@ func (b *generalBuiltin) Name() ast.Identifier {
} }
func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { 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) builtinTrace := getBuiltinTrace(trace, b.name)
values := make([]value, len(flatArgs)) values := make([]value, len(flatArgs))
for j := 0; j < len(values); j++ { 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 // 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 functionID = &valueFunction{ec: builtinID}
var bopBuiltins = []*binaryBuiltin{ var bopBuiltins = []*binaryBuiltin{
// Note that % and `in` are desugared instead of being handled here // Note that % and `in` are desugared instead of being handled here
ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, parameters: ast.Identifiers{"x", "y"}}, ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, params: ast.Identifiers{"x", "y"}},
ast.BopDiv: &binaryBuiltin{name: "operator/", function: builtinDiv, parameters: 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.BopPlus: &binaryBuiltin{name: "operator+", function: builtinPlus, params: ast.Identifiers{"x", "y"}},
ast.BopMinus: &binaryBuiltin{name: "operator-", function: builtinMinus, parameters: 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.BopShiftL: &binaryBuiltin{name: "operator<<", function: builtinShiftL, params: ast.Identifiers{"x", "y"}},
ast.BopShiftR: &binaryBuiltin{name: "operator>>", function: builtinShiftR, parameters: 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.BopGreater: &binaryBuiltin{name: "operator>", function: builtinGreater, params: ast.Identifiers{"x", "y"}},
ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, parameters: ast.Identifiers{"x", "y"}}, ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, params: ast.Identifiers{"x", "y"}},
ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, parameters: ast.Identifiers{"x", "y"}}, ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, params: ast.Identifiers{"x", "y"}},
ast.BopLessEq: &binaryBuiltin{name: "operator<=", function: builtinLessEq, parameters: 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.BopManifestEqual: &binaryBuiltin{name: "operator==", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
ast.BopManifestUnequal: &binaryBuiltin{name: "operator!=", function: builtinNotEquals, parameters: ast.Identifiers{"x", "y"}}, // Special case 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.BopBitwiseAnd: &binaryBuiltin{name: "operator&", function: builtinBitwiseAnd, params: ast.Identifiers{"x", "y"}},
ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, parameters: ast.Identifiers{"x", "y"}}, ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, params: ast.Identifiers{"x", "y"}},
ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, parameters: ast.Identifiers{"x", "y"}}, ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, params: ast.Identifiers{"x", "y"}},
} }
var uopBuiltins = []*unaryBuiltin{ var uopBuiltins = []*unaryBuiltin{
ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, parameters: ast.Identifiers{"x"}}, ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, params: ast.Identifiers{"x"}},
ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, parameters: ast.Identifiers{"x"}}, ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, params: ast.Identifiers{"x"}},
ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, parameters: ast.Identifiers{"x"}}, ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, params: ast.Identifiers{"x"}},
ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, parameters: ast.Identifiers{"x"}}, ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, params: ast.Identifiers{"x"}},
} }
func buildBuiltinMap(builtins []builtin) map[string]evalCallable { func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
@ -1437,51 +1426,51 @@ func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
var funcBuiltins = buildBuiltinMap([]builtin{ var funcBuiltins = buildBuiltinMap([]builtin{
builtinID, builtinID,
&unaryBuiltin{name: "extVar", function: builtinExtVar, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "extVar", function: builtinExtVar, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "length", function: builtinLength, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "length", function: builtinLength, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "toString", function: builtinToString, parameters: ast.Identifiers{"a"}}, &unaryBuiltin{name: "toString", function: builtinToString, params: ast.Identifiers{"a"}},
&binaryBuiltin{name: "trace", function: builtinTrace, parameters: ast.Identifiers{"str", "rest"}}, &binaryBuiltin{name: "trace", function: builtinTrace, params: ast.Identifiers{"str", "rest"}},
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, parameters: ast.Identifiers{"sz", "func"}}, &binaryBuiltin{name: "makeArray", function: builtinMakeArray, params: ast.Identifiers{"sz", "func"}},
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, parameters: ast.Identifiers{"func", "arr"}}, &binaryBuiltin{name: "flatMap", function: builtinFlatMap, params: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "join", function: builtinJoin, parameters: ast.Identifiers{"sep", "arr"}}, &binaryBuiltin{name: "join", function: builtinJoin, params: ast.Identifiers{"sep", "arr"}},
&unaryBuiltin{name: "reverse", function: builtinReverse, parameters: ast.Identifiers{"arr"}}, &unaryBuiltin{name: "reverse", function: builtinReverse, params: ast.Identifiers{"arr"}},
&binaryBuiltin{name: "filter", function: builtinFilter, parameters: ast.Identifiers{"func", "arr"}}, &binaryBuiltin{name: "filter", function: builtinFilter, params: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "range", function: builtinRange, parameters: ast.Identifiers{"from", "to"}}, &binaryBuiltin{name: "range", function: builtinRange, params: ast.Identifiers{"from", "to"}},
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, parameters: ast.Identifiers{"x", "y"}}, &binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, params: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "equals", function: builtinEquals, parameters: ast.Identifiers{"x", "y"}}, &binaryBuiltin{name: "equals", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, parameters: ast.Identifiers{"obj", "hidden"}}, &binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, params: ast.Identifiers{"obj", "hidden"}},
&ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, parameters: ast.Identifiers{"obj", "fname", "hidden"}}, &ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, params: ast.Identifiers{"obj", "fname", "hidden"}},
&unaryBuiltin{name: "type", function: builtinType, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "type", function: builtinType, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "char", function: builtinChar, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "char", function: builtinChar, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "codepoint", function: builtinCodepoint, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "codepoint", function: builtinCodepoint, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "ceil", function: builtinCeil, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "ceil", function: builtinCeil, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "floor", function: builtinFloor, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "floor", function: builtinFloor, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sqrt", function: builtinSqrt, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "sqrt", function: builtinSqrt, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sin", function: builtinSin, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "sin", function: builtinSin, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "cos", function: builtinCos, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "cos", function: builtinCos, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "tan", function: builtinTan, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "tan", function: builtinTan, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "asin", function: builtinAsin, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "asin", function: builtinAsin, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "acos", function: builtinAcos, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "acos", function: builtinAcos, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "atan", function: builtinAtan, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "atan", function: builtinAtan, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "log", function: builtinLog, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "log", function: builtinLog, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exp", function: builtinExp, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "exp", function: builtinExp, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "mantissa", function: builtinMantissa, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "mantissa", function: builtinMantissa, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exponent", function: builtinExponent, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "exponent", function: builtinExponent, params: ast.Identifiers{"x"}},
&binaryBuiltin{name: "pow", function: builtinPow, parameters: ast.Identifiers{"base", "exp"}}, &binaryBuiltin{name: "pow", function: builtinPow, params: ast.Identifiers{"base", "exp"}},
&binaryBuiltin{name: "modulo", function: builtinModulo, parameters: ast.Identifiers{"x", "y"}}, &binaryBuiltin{name: "modulo", function: builtinModulo, params: ast.Identifiers{"x", "y"}},
&unaryBuiltin{name: "md5", function: builtinMd5, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "md5", function: builtinMd5, params: ast.Identifiers{"x"}},
&ternaryBuiltin{name: "substr", function: builtinSubstr, parameters: ast.Identifiers{"str", "from", "len"}}, &ternaryBuiltin{name: "substr", function: builtinSubstr, params: ast.Identifiers{"str", "from", "len"}},
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, parameters: ast.Identifiers{"str", "c", "maxsplits"}}, &ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, params: ast.Identifiers{"str", "c", "maxsplits"}},
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, parameters: ast.Identifiers{"str", "from", "to"}}, &ternaryBuiltin{name: "strReplace", function: builtinStrReplace, params: ast.Identifiers{"str", "from", "to"}},
&unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, parameters: ast.Identifiers{"str"}}, &unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, parameters: ast.Identifiers{"str"}}, &unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "parseJson", function: builtinParseJSON, parameters: ast.Identifiers{"str"}}, &unaryBuiltin{name: "parseJson", function: builtinParseJSON, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64", function: builtinBase64, parameters: ast.Identifiers{"input"}}, &unaryBuiltin{name: "base64", function: builtinBase64, params: ast.Identifiers{"input"}},
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, parameters: ast.Identifiers{"str"}}, &unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, parameters: ast.Identifiers{"arr"}}, &unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}},
&generalBuiltin{name: "sort", function: builtinSort, parameters: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}}, &generalBuiltin{name: "sort", function: builtinSort, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
&unaryBuiltin{name: "native", function: builtinNative, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}},
// internal // internal
&unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, parameters: ast.Identifiers{"x"}}, &unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, params: ast.Identifiers{"x"}},
}) })

View File

@ -8,18 +8,15 @@ import (
"testing" "testing"
) )
var jsonnetPath string var (
var outputPassthru bool jsonnetPath = flag.String("jsonnetPath", "./jsonnet", "Path to jsonnet binary")
outputPassthru = flag.Bool("outputPassthru", false, "Pass stdout/err from jsonnet")
func init() { )
flag.StringVar(&jsonnetPath, "jsonnetPath", "./jsonnet", "Path to jsonnet binary")
flag.BoolVar(&outputPassthru, "outputPassthru", false, "Pass stdout/err from jsonnet")
}
func RunBenchmark(b *testing.B, name string) { func RunBenchmark(b *testing.B, name string) {
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
cmd := exec.Command(jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name)) cmd := exec.Command(*jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
if outputPassthru { if *outputPassthru {
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
} }

View File

@ -103,7 +103,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
id, err := handles.make(newVM) id, err := handles.make(newVM)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
@ -113,7 +113,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
//export jsonnet_destroy //export jsonnet_destroy
func jsonnet_destroy(vmRef *C.struct_JsonnetVm) { func jsonnet_destroy(vmRef *C.struct_JsonnetVm) {
if err := handles.free(uint32(vmRef.id)); err != nil { if err := handles.free(uint32(vmRef.id)); err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
@ -124,14 +124,14 @@ func getVM(vmRef *C.struct_JsonnetVm) *vm {
ref, err := handles.get(uint32(vmRef.id)) ref, err := handles.get(uint32(vmRef.id))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
v, ok := ref.(*vm) v, ok := ref.(*vm)
if !ok { 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) 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 { if err := handles.free(uint32(v.id)); err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) 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}) id, err := handles.make(&jsonValue{val: val})
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
@ -435,7 +435,7 @@ func getJSONValue(jsonRef *C.struct_JsonnetJsonValue) *jsonValue {
ref, err := handles.get(uint32(jsonRef.id)) ref, err := handles.get(uint32(jsonRef.id))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }

View File

@ -44,8 +44,14 @@ func main() {
ast := dump.Sdump(node) ast := dump.Sdump(node)
dst := os.Stdout dst := os.Stdout
dst.WriteString(header) _, err = dst.WriteString(header)
dst.WriteString(ast) if err != nil {
panic(err)
}
_, err = dst.WriteString(ast)
if err != nil {
panic(err)
}
} }
var header = ` var header = `

View File

@ -341,7 +341,7 @@ func readInput(config config, filename *string) (input string, err error) {
return 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 // If multiple file output is used, then iterate over each string from
// the sequence of strings returned by jsonnet_evaluate_snippet_multi, // the sequence of strings returned by jsonnet_evaluate_snippet_multi,
// construct pairs of filename and content, and write each output file. // 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 == "" { if outputFile == "" {
manifest = os.Stdout manifest = os.Stdout
} else { } else {
var err error
manifest, err = os.Create(outputFile) manifest, err = os.Create(outputFile)
if err != nil { if err != nil {
return err return err
} }
defer manifest.Close() defer func() {
if ferr := manifest.Close(); err != nil {
err = ferr
}
}()
} }
// Iterate through the map in order. // Iterate through the map in order.
@ -401,7 +404,11 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
_, err = f.WriteString(newContent) _, err = f.WriteString(newContent)
if err != nil { if err != nil {
@ -413,18 +420,21 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
} }
// writeOutputStream writes the output as a YAML stream. // 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 var f *os.File
if outputFile == "" { if outputFile == "" {
f = os.Stdout f = os.Stdout
} else { } else {
var err error
f, err = os.Create(outputFile) f, err = os.Create(outputFile)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
} }
for _, doc := range output { for _, doc := range output {
@ -448,7 +458,7 @@ func writeOutputStream(output []string, outputFile string) error {
return nil return nil
} }
func writeOutputFile(output string, outputFile string, createDirs bool) error { func writeOutputFile(output string, outputFile string, createDirs bool) (err error) {
if outputFile == "" { if outputFile == "" {
fmt.Print(output) fmt.Print(output)
return nil return nil
@ -460,11 +470,15 @@ func writeOutputFile(output string, outputFile string, createDirs bool) error {
} }
} }
f, err := os.Create(outputFile) f, createErr := os.Create(outputFile)
if err != nil { if createErr != nil {
return err return err
} }
defer f.Close() defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
_, err = f.WriteString(output) _, err = f.WriteString(output)
return err return err
@ -478,7 +492,10 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
pprof.StartCPUProfile(f) err = pprof.StartCPUProfile(f)
if err != nil {
log.Fatal(err)
}
defer pprof.StopCPUProfile() defer pprof.StopCPUProfile()
} }
@ -519,7 +536,7 @@ func main() {
if len(config.inputFiles) != 1 { if len(config.inputFiles) != 1 {
// Should already have been caught by processArgs. // 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] filename := config.inputFiles[0]
input, err := readInput(config, &filename) input, err := readInput(config, &filename)
@ -560,7 +577,11 @@ func main() {
if err := pprof.WriteHeapProfile(f); err != nil { if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err) 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 { if err != nil {

View File

@ -105,7 +105,7 @@ func (ef *termErrorFormatter) showCode(buf *bytes.Buffer, loc ast.LocationRange)
beginning := ast.LineBeginning(&loc) beginning := ast.LineBeginning(&loc)
ending := ast.LineEnding(&loc) ending := ast.LineEnding(&loc)
fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(beginning)) 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)) fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(ending))
buf.WriteByte('\n') buf.WriteByte('\n')
} }

View File

@ -29,7 +29,7 @@ import (
"strconv" "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 // Options represents configuration option
type Options struct { type Options struct {
@ -59,16 +59,22 @@ type dumpState struct {
reusedPointers []uintptr reusedPointers []uintptr
primitivePointers []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() { 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() { func (s *dumpState) newline() {
s.w.Write([]byte("\n")) mustWrite(s.w, []byte("\n"))
} }
func (s *dumpState) dumpType(v reflect.Value) { func (s *dumpState) dumpType(v reflect.Value) {
@ -78,34 +84,34 @@ func (s *dumpState) dumpType(v reflect.Value) {
} else if s.homePackageRegexp != nil { } else if s.homePackageRegexp != nil {
typeName = s.homePackageRegexp.ReplaceAllLiteralString(typeName, "") typeName = s.homePackageRegexp.ReplaceAllLiteralString(typeName, "")
} }
s.w.Write([]byte(typeName)) mustWrite(s.w, []byte(typeName))
} }
func (s *dumpState) dumpSlice(v reflect.Value) { func (s *dumpState) dumpSlice(v reflect.Value) {
s.dumpType(v) s.dumpType(v)
numEntries := v.Len() numEntries := v.Len()
if numEntries == 0 { if numEntries == 0 {
s.w.Write([]byte("{}")) mustWrite(s.w, []byte("{}"))
return return
} }
s.w.Write([]byte("{")) mustWrite(s.w, []byte("{"))
s.newline() s.newline()
s.depth++ s.depth++
for i := 0; i < numEntries; i++ { for i := 0; i < numEntries; i++ {
s.indent() s.indent()
s.dumpVal(v.Index(i)) s.dumpVal(v.Index(i))
s.w.Write([]byte(",")) mustWrite(s.w, []byte(","))
s.newline() s.newline()
} }
s.depth-- s.depth--
s.indent() s.indent()
s.w.Write([]byte("}")) mustWrite(s.w, []byte("}"))
} }
func (s *dumpState) dumpStruct(v reflect.Value) { func (s *dumpState) dumpStruct(v reflect.Value) {
dumpPreamble := func() { dumpPreamble := func() {
s.dumpType(v) s.dumpType(v)
s.w.Write([]byte("{")) mustWrite(s.w, []byte("{"))
s.newline() s.newline()
s.depth++ s.depth++
} }
@ -122,26 +128,26 @@ func (s *dumpState) dumpStruct(v reflect.Value) {
preambleDumped = true preambleDumped = true
} }
s.indent() s.indent()
s.w.Write([]byte(vtf.Name)) mustWrite(s.w, []byte(vtf.Name))
s.w.Write([]byte(": ")) mustWrite(s.w, []byte(": "))
s.dumpVal(v.Field(i)) s.dumpVal(v.Field(i))
s.w.Write([]byte(",")) mustWrite(s.w, []byte(","))
s.newline() s.newline()
} }
if preambleDumped { if preambleDumped {
s.depth-- s.depth--
s.indent() s.indent()
s.w.Write([]byte("}")) mustWrite(s.w, []byte("}"))
} else { } else {
// There were no fields dumped // There were no fields dumped
s.dumpType(v) s.dumpType(v)
s.w.Write([]byte("{}")) mustWrite(s.w, []byte("{}"))
} }
} }
func (s *dumpState) dumpMap(v reflect.Value) { func (s *dumpState) dumpMap(v reflect.Value) {
s.dumpType(v) s.dumpType(v)
s.w.Write([]byte("{")) mustWrite(s.w, []byte("{"))
s.newline() s.newline()
s.depth++ s.depth++
keys := v.MapKeys() keys := v.MapKeys()
@ -149,14 +155,14 @@ func (s *dumpState) dumpMap(v reflect.Value) {
for _, key := range keys { for _, key := range keys {
s.indent() s.indent()
s.dumpVal(key) s.dumpVal(key)
s.w.Write([]byte(": ")) mustWrite(s.w, []byte(": "))
s.dumpVal(v.MapIndex(key)) s.dumpVal(v.MapIndex(key))
s.w.Write([]byte(",")) mustWrite(s.w, []byte(","))
s.newline() s.newline()
} }
s.depth-- s.depth--
s.indent() s.indent()
s.w.Write([]byte("}")) mustWrite(s.w, []byte("}"))
} }
func (s *dumpState) dump(value interface{}) { func (s *dumpState) dump(value interface{}) {
@ -164,7 +170,7 @@ func (s *dumpState) dump(value interface{}) {
if s.config.VariableDescription != "" { if s.config.VariableDescription != "" {
fmt.Fprintf(s.w, "\n// %s\n", 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 { if value == nil {
@ -194,11 +200,11 @@ func (s *dumpState) dump(value interface{}) {
s.dumpVal(v) s.dumpVal(v)
s.w = oldWriter s.w = oldWriter
if buf.Len() > 100 { if buf.Len() > 100 {
s.w.Write([]byte("_" + s.config.VariableName)) mustWrite(s.w, []byte("_"+s.config.VariableName))
s.newline() 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() s.newline()
} }
@ -206,7 +212,7 @@ func (s *dumpState) dump(value interface{}) {
func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName string) { func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName string) {
v := deInterface(value) v := deInterface(value)
s.w.Write([]byte("var " + pointerName + "Var" + " = ")) mustWrite(s.w, []byte("var "+pointerName+"Var"+" = "))
switch v.Kind() { switch v.Kind() {
case reflect.Bool: case reflect.Bool:
printBool(s.w, v.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) printComplex(s.w, v.Complex(), 64)
case reflect.String: case reflect.String:
s.w.Write([]byte(strconv.Quote(v.String()))) mustWrite(s.w, []byte(strconv.Quote(v.String())))
} }
s.newline() s.newline()
s.w.Write([]byte("var " + pointerName + " = &" + pointerName + "Var")) mustWrite(s.w, []byte("var "+pointerName+" = &"+pointerName+"Var"))
s.newline() s.newline()
} }
@ -263,7 +269,7 @@ func (s *dumpState) dumpPrimitivePointerVal(value reflect.Value) {
case reflect.Invalid: case reflect.Invalid:
// Do nothing. We should never get here since invalid has already // Do nothing. We should never get here since invalid has already
// been handled above. // been handled above.
s.w.Write([]byte("<invalid>")) mustWrite(s.w, []byte("<invalid>"))
case reflect.Slice: case reflect.Slice:
if v.IsNil() { if v.IsNil() {
@ -310,7 +316,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
case reflect.Invalid: case reflect.Invalid:
// Do nothing. We should never get here since invalid has already // Do nothing. We should never get here since invalid has already
// been handled above. // been handled above.
s.w.Write([]byte("<invalid>")) mustWrite(s.w, []byte("<invalid>"))
case reflect.Slice: case reflect.Slice:
if v.IsNil() { if v.IsNil() {
@ -338,7 +344,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
case reflect.Ptr: case reflect.Ptr:
pointerName, isReused, isPrimitive, isFirstVisit := s.nameForPointer(v), s.isReusedPointer(v), s.isPrimitivePointer(v), s.visitPointerAndCheckIfFirstTime(v) pointerName, isReused, isPrimitive, isFirstVisit := s.nameForPointer(v), s.isReusedPointer(v), s.isPrimitivePointer(v), s.visitPointerAndCheckIfFirstTime(v)
if isReused && !isPrimitive && isFirstVisit { if isReused && !isPrimitive && isFirstVisit {
s.w.Write([]byte("var " + pointerName + " = &")) mustWrite(s.w, []byte("var "+pointerName+" = &"))
s.dumpVal(v.Elem()) s.dumpVal(v.Elem())
s.newline() s.newline()
} else { } else {
@ -349,7 +355,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
func (s *dumpState) dumpVal(value reflect.Value) { func (s *dumpState) dumpVal(value reflect.Value) {
if value.Kind() == reflect.Ptr && value.IsNil() { if value.Kind() == reflect.Ptr && value.IsNil() {
s.w.Write([]byte("nil")) mustWrite(s.w, []byte("nil"))
return return
} }
@ -359,7 +365,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
case reflect.Invalid: case reflect.Invalid:
// Do nothing. We should never get here since invalid has already // Do nothing. We should never get here since invalid has already
// been handled above. // been handled above.
s.w.Write([]byte("<invalid>")) mustWrite(s.w, []byte("<invalid>"))
case reflect.Bool: case reflect.Bool:
printBool(s.w, v.Bool()) printBool(s.w, v.Bool())
@ -397,7 +403,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
printComplex(s.w, v.Complex(), 64) printComplex(s.w, v.Complex(), 64)
case reflect.String: case reflect.String:
s.w.Write([]byte(strconv.Quote(v.String()))) mustWrite(s.w, []byte(strconv.Quote(v.String())))
case reflect.Slice: case reflect.Slice:
if v.IsNil() { if v.IsNil() {
@ -419,9 +425,9 @@ func (s *dumpState) dumpVal(value reflect.Value) {
case reflect.Ptr: case reflect.Ptr:
pointerName, isPrimitive, isReused := s.nameForPointer(v), s.isPrimitivePointer(v), s.isReusedPointer(v) pointerName, isPrimitive, isReused := s.nameForPointer(v), s.isPrimitivePointer(v), s.isReusedPointer(v)
if isPrimitive || isReused { if isPrimitive || isReused {
s.w.Write([]byte(pointerName)) mustWrite(s.w, []byte(pointerName))
} else { } else {
s.w.Write([]byte("&")) mustWrite(s.w, []byte("&"))
s.dumpVal(v.Elem()) 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 { func (s *dumpState) nameForPointer(v reflect.Value) string {
if isPointerValue(v) { if isPointerValue(v) {
ptr := v.Pointer() ptr := v.Pointer()

View File

@ -25,42 +25,42 @@ import (
) )
func printBool(w io.Writer, value bool) { 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) { 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.") { if stripPackageName && strings.HasPrefix(typeName, "ast.") {
typeName = typeName[4:] 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) { func printUint(w io.Writer, val reflect.Value) {
typeName := fmt.Sprintf("%s", val.Type()) typeName := val.Type().String()
w.Write([]byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10)))) mustWrite(w, []byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10))))
} }
func printFloat(w io.Writer, val float64, precision int, floatType string) { 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) { func printComplex(w io.Writer, c complex128, floatPrecision int) {
w.Write([]byte("complex")) mustWrite(w, []byte("complex"))
w.Write([]byte(fmt.Sprintf("%d", floatPrecision*2))) mustWrite(w, []byte(fmt.Sprintf("%d", floatPrecision*2)))
r := real(c) r := real(c)
w.Write([]byte("(")) mustWrite(w, []byte("("))
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) mustWrite(w, []byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
i := imag(c) i := imag(c)
if i >= 0 { if i >= 0 {
w.Write([]byte("+")) mustWrite(w, []byte("+"))
} }
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) mustWrite(w, []byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
w.Write([]byte("i)")) mustWrite(w, []byte("i)"))
} }
func printNil(w io.Writer) { func printNil(w io.Writer) {
w.Write([]byte("nil")) mustWrite(w, []byte("nil"))
} }
// deInterface returns values inside of non-nil interfaces when possible. // deInterface returns values inside of non-nil interfaces when possible.

View File

@ -412,16 +412,13 @@ func (l *lexer) lexWhitespace() (int, int) {
switch r { switch r {
case '\r': case '\r':
// Ignore. // Ignore.
break
case '\n': case '\n':
indent = 0 indent = 0
newLines++ newLines++
break
case ' ': case ' ':
indent++ indent++
break
// This only works for \t at the beginning of lines, but we strip it everywhere else // 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 // 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. // is enabled it will be fixed later.
case '\t': case '\t':
indent += 8 indent += 8
break
} }
} }
l.backup() l.backup()
@ -489,7 +485,7 @@ func (l *lexer) lexNumber() error {
state := numBegin state := numBegin
outerLoop: outerLoop:
for true { for {
r := l.next() r := l.next()
switch state { switch state {
case numBegin: case numBegin:
@ -654,6 +650,7 @@ func (l *lexer) lexSymbol() error {
margin := l.pos.byteNo - l.pos.lineStart margin := l.pos.byteNo - l.pos.lineStart
commentStartLoc := l.tokenStartLoc commentStartLoc := l.tokenStartLoc
//nolint:ineffassign,staticcheck
r := l.next() // consume the initial '*' r := l.next() // consume the initial '*'
for r = l.next(); r != '*' || l.peek() != '/'; r = l.next() { for r = l.next(); r != '*' || l.peek() != '/'; r = l.next() {
if r == lexEOF { if r == lexEOF {
@ -687,9 +684,9 @@ func (l *lexer) lexSymbol() error {
} }
} }
if allStar { if allStar {
for _, l := range lines { for i := range lines {
if l[0] == '*' { if lines[i][0] == '*' {
l = " " + l lines[i] = " " + lines[i]
} }
} }
} }
@ -813,7 +810,7 @@ func Lex(fn string, input string) (Tokens, error) {
l := makeLexer(fn, input) l := makeLexer(fn, input)
var err error var err error
for true { for {
newLines, indent := l.lexWhitespace() newLines, indent := l.lexWhitespace()
// If it's the end of the file, discard final whitespace. // If it's the end of the file, discard final whitespace.
if l.peek() == lexEOF { if l.peek() == lexEOF {
@ -855,7 +852,8 @@ func Lex(fn string, input string) (Tokens, error) {
return nil, err return nil, err
} }
// String literals // String literals
case '"': case '"':
stringStartLoc := l.prevLocation() stringStartLoc := l.prevLocation()
for r = l.next(); ; r = l.next() { for r = l.next(); ; r = l.next() {
@ -869,6 +867,7 @@ func Lex(fn string, input string) (Tokens, error) {
break break
} }
if r == '\\' && l.peek() != lexEOF { if r == '\\' && l.peek() != lexEOF {
//nolint:ineffassign,staticcheck
r = l.next() r = l.next()
} }
} }
@ -885,6 +884,7 @@ func Lex(fn string, input string) (Tokens, error) {
break break
} }
if r == '\\' && l.peek() != lexEOF { if r == '\\' && l.peek() != lexEOF {
//nolint:ineffassign,staticcheck
r = l.next() r = l.next()
} }
} }

View File

@ -21,127 +21,10 @@ import (
"github.com/google/go-jsonnet/ast" "github.com/google/go-jsonnet/ast"
) )
type lexTest struct {
name string
input string
tokens Tokens
errString string
}
var ( var (
tEOF = token{kind: tokenEndOfFile} 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 { func fodderEqual(f1 ast.Fodder, f2 ast.Fodder) bool {
if len(f1) != len(f2) { if len(f1) != len(f2) {
return false return false

View File

@ -120,16 +120,6 @@ func (p *parser) doublePeek() *token {
return &p.t[p.currT+1] 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. // parseArgument parses either <f1> id <f2> = expr or just expr.
// It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr) // It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr)
// respectively. // respectively.

View File

@ -167,7 +167,10 @@ func desugarFields(nodeBase ast.NodeBase, fields *ast.ObjectFields, objLevel int
return nil, err return nil, err
} }
} }
desugarLocalBinds(locals, objLevel+1) err := desugarLocalBinds(locals, objLevel+1)
if err != nil {
return nil, err
}
for i := range desugaredFields { for i := range desugaredFields {
field := &(desugaredFields[i]) field := &(desugaredFields[i])
if field.Name != nil { if field.Name != nil {

View File

@ -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. // Build a binding frame containing specified variables.
func (s *callStack) capture(freeVars ast.Identifiers) bindingFrame { func (s *callStack) capture(freeVars ast.Identifiers) bindingFrame {
env := make(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. // too large to fit in a double.
num, err := strconv.ParseFloat(node.OriginalString, 64) num, err := strconv.ParseFloat(node.OriginalString, 64)
if err != nil { if err != nil {
return nil, i.Error(fmt.Sprintf("overflow"), trace) return nil, i.Error("overflow", trace)
} }
return makeValueNumber(num), nil 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) { func (i *interpreter) evaluateNumber(pv potentialValue, trace traceElement) (*valueNumber, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { if err != nil {
@ -998,6 +991,7 @@ func (i *interpreter) evaluateInt(pv potentialValue, trace traceElement) (int, e
return i.getInt(v, trace) return i.getInt(v, trace)
} }
//nolint:unused
func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) { func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
num, err := i.getNumber(val, trace) num, err := i.getNumber(val, trace)
if err != nil { if err != nil {
@ -1010,6 +1004,7 @@ func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
return intNum, nil return intNum, nil
} }
//nolint:unused
func (i *interpreter) evaluateInt64(pv potentialValue, trace traceElement) (int64, error) { func (i *interpreter) evaluateInt64(pv potentialValue, trace traceElement) (int64, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { 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) { func (i *interpreter) evaluateString(pv potentialValue, trace traceElement) (valueString, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { 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) { func (i *interpreter) evaluateBoolean(pv potentialValue, trace traceElement) (*valueBoolean, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { 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) { func (i *interpreter) evaluateArray(pv potentialValue, trace traceElement) (*valueArray, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { 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) { func (i *interpreter) evaluateFunction(pv potentialValue, trace traceElement) (*valueFunction, error) {
v, err := i.evaluatePV(pv, trace) v, err := i.evaluatePV(pv, trace)
if err != nil { if err != nil {

View File

@ -39,7 +39,10 @@ func main() {
if err != nil { if err != nil {
die(err) die(err)
} }
inputFile.Close() err = inputFile.Close()
if err != nil {
die(err)
}
node, err := jsonnet.SnippetToAST(p, string(data)) node, err := jsonnet.SnippetToAST(p, string(data))
if err != nil { if err != nil {
die(err) die(err)

View File

@ -17,7 +17,10 @@ type ErrorWriter struct {
func (e *ErrorWriter) writeError(err errors.StaticError) { func (e *ErrorWriter) writeError(err errors.StaticError) {
e.ErrorsFound = true 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 { type variable struct {

View File

@ -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() t.Helper()
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
@ -407,8 +407,11 @@ func withinWorkingDirectory(t *testing.T, dir string) func() error {
if err := os.Chdir(dir); err != nil { if err := os.Chdir(dir); err != nil {
t.Fatal(err) t.Fatal(err)
} }
return func() error { return func() {
return os.Chdir(cwd) 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 { if dir, err = ioutil.TempDir("", "jsonnet"); err != nil {
t.Fatal(err) 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) { copySmallFile := func(t *testing.T, dst, src string) {

View File

@ -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"]]) std.sort([1, [error "foo"]])
------------------------------------------------- -------------------------------------------------
During manifestation During evaluation

View File

@ -36,19 +36,9 @@ func (rv *readyValue) evaluate(i *interpreter, trace traceElement, sb selfBindin
return rv.content, nil return rv.content, nil
} }
func (rv *readyValue) aPotentialValue() {}
// potentialValues // 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 // cachedThunk is a wrapper that caches the value of a potentialValue after
// the first evaluation. // the first evaluation.
// Note: All potentialValues are required to provide the same value every time, // 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) { 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 { for variable, pvalue := range origBindings {
upValues[variable] = pvalue 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) { func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) {
argThunks := make(bindingFrame) argThunks := make(bindingFrame)
parameters := closure.Parameters() parameters := closure.parameters()
for i, arg := range arguments.positional { for i, arg := range arguments.positional {
argThunks[parameters[i].name] = arg 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) return i.EvalInCleanEnv(trace, &calledEnvironment, closure.function.Body, arguments.tailstrict)
} }
func (closure *closure) Parameters() []namedParameter { func (closure *closure) parameters() []namedParameter {
return closure.params return closure.params
} }
@ -232,7 +221,7 @@ type NativeFunction struct {
// evalCall evaluates a call to a NativeFunction and returns the result. // evalCall evaluates a call to a NativeFunction and returns the result.
func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) { 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)) nativeArgs := make([]interface{}, 0, len(flatArgs))
for _, arg := range flatArgs { for _, arg := range flatArgs {
v, err := i.evaluatePV(arg, trace) v, err := i.evaluatePV(arg, trace)
@ -253,20 +242,10 @@ func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter,
} }
// Parameters returns a NativeFunction's parameters. // Parameters returns a NativeFunction's parameters.
func (native *NativeFunction) Parameters() []namedParameter { func (native *NativeFunction) parameters() []namedParameter {
ret := make([]namedParameter, len(native.Params)) ret := make([]namedParameter, len(native.Params))
for i := range ret { for i := range ret {
ret[i].name = native.Params[i] ret[i].name = native.Params[i]
} }
return ret return ret
} }
// -------------------------------------
type defaultArgument struct {
body ast.Node
}
func (da *defaultArgument) inEnv(env *environment) potentialValue {
return &cachedThunk{env: env, body: da.body}
}

View File

@ -313,9 +313,7 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
arrayElems = elements arrayElems = elements
} else { } else {
arrayElems = make([]*cachedThunk, len(elements)) arrayElems = make([]*cachedThunk, len(elements))
for i := range elements { copy(arrayElems, elements)
arrayElems[i] = elements[i]
}
} }
return &valueArray{ return &valueArray{
elements: arrayElems, elements: arrayElems,
@ -324,12 +322,8 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
func concatArrays(a, b *valueArray) *valueArray { func concatArrays(a, b *valueArray) *valueArray {
result := make([]*cachedThunk, 0, len(a.elements)+len(b.elements)) result := make([]*cachedThunk, 0, len(a.elements)+len(b.elements))
for _, r := range a.elements { result = append(result, a.elements...)
result = append(result, r) result = append(result, b.elements...)
}
for _, r := range b.elements {
result = append(result, r)
}
return &valueArray{elements: result} return &valueArray{elements: result}
} }
@ -348,19 +342,19 @@ type valueFunction struct {
// TODO(sbarzowski) better name? // TODO(sbarzowski) better name?
type evalCallable interface { type evalCallable interface {
evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) 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) { 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 { if err != nil {
return nil, err return nil, err
} }
return f.ec.evalCall(args, i, trace) return f.ec.evalCall(args, i, trace)
} }
func (f *valueFunction) Parameters() []namedParameter { func (f *valueFunction) parameters() []namedParameter {
return f.ec.Parameters() return f.ec.parameters()
} }
func checkArguments(i *interpreter, trace traceElement, args callArguments, params []namedParameter) error { func checkArguments(i *interpreter, trace traceElement, args callArguments, params []namedParameter) error {
@ -406,22 +400,11 @@ func (f *valueFunction) getType() *valueType {
return functionType 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 { type namedParameter struct {
name ast.Identifier name ast.Identifier
defaultArg ast.Node defaultArg ast.Node
} }
type potentialValueInEnv interface {
inEnv(env *environment) *cachedThunk
}
type callArguments struct { type callArguments struct {
positional []*cachedThunk positional []*cachedThunk
named []namedCallArgument named []namedCallArgument