diff --git a/builtins.go b/builtins.go index 37cace5..f4bb5eb 100644 --- a/builtins.go +++ b/builtins.go @@ -33,11 +33,11 @@ import ( "github.com/google/go-jsonnet/ast" ) -func builtinPlus(i *interpreter, trace traceElement, x, y value) (value, error) { +func builtinPlus(i *interpreter, x, y value) (value, error) { // TODO(sbarzowski) perhaps a more elegant way to dispatch switch right := y.(type) { case valueString: - left, err := builtinToString(i, trace, x) + left, err := builtinToString(i, x) if err != nil { return nil, err } @@ -46,13 +46,13 @@ func builtinPlus(i *interpreter, trace traceElement, x, y value) (value, error) } switch left := x.(type) { case *valueNumber: - right, err := i.getNumber(y, trace) + right, err := i.getNumber(y) if err != nil { return nil, err } - return makeDoubleCheck(i, trace, left.value+right.value) + return makeDoubleCheck(i, left.value+right.value) case valueString: - right, err := builtinToString(i, trace, y) + right, err := builtinToString(i, y) if err != nil { return nil, err } @@ -62,110 +62,110 @@ func builtinPlus(i *interpreter, trace traceElement, x, y value) (value, error) case *valueObject: return makeValueExtendedObject(left, right), nil default: - return nil, i.typeErrorSpecific(y, &valueObject{}, trace) + return nil, i.typeErrorSpecific(y, &valueObject{}) } case *valueArray: - right, err := i.getArray(y, trace) + right, err := i.getArray(y) if err != nil { return nil, err } return concatArrays(left, right), nil default: - return nil, i.typeErrorGeneral(x, trace) + return nil, i.typeErrorGeneral(x) } } -func builtinMinus(i *interpreter, trace traceElement, xv, yv value) (value, error) { - x, err := i.getNumber(xv, trace) +func builtinMinus(i *interpreter, xv, yv value) (value, error) { + x, err := i.getNumber(xv) if err != nil { return nil, err } - y, err := i.getNumber(yv, trace) + y, err := i.getNumber(yv) if err != nil { return nil, err } - return makeDoubleCheck(i, trace, x.value-y.value) + return makeDoubleCheck(i, x.value-y.value) } -func builtinMult(i *interpreter, trace traceElement, xv, yv value) (value, error) { - x, err := i.getNumber(xv, trace) +func builtinMult(i *interpreter, xv, yv value) (value, error) { + x, err := i.getNumber(xv) if err != nil { return nil, err } - y, err := i.getNumber(yv, trace) + y, err := i.getNumber(yv) if err != nil { return nil, err } - return makeDoubleCheck(i, trace, x.value*y.value) + return makeDoubleCheck(i, x.value*y.value) } -func builtinDiv(i *interpreter, trace traceElement, xv, yv value) (value, error) { - x, err := i.getNumber(xv, trace) +func builtinDiv(i *interpreter, xv, yv value) (value, error) { + x, err := i.getNumber(xv) if err != nil { return nil, err } - y, err := i.getNumber(yv, trace) + y, err := i.getNumber(yv) if err != nil { return nil, err } if y.value == 0 { - return nil, i.Error("Division by zero.", trace) + return nil, i.Error("Division by zero.") } - return makeDoubleCheck(i, trace, x.value/y.value) + return makeDoubleCheck(i, x.value/y.value) } -func builtinModulo(i *interpreter, trace traceElement, xv, yv value) (value, error) { - x, err := i.getNumber(xv, trace) +func builtinModulo(i *interpreter, xv, yv value) (value, error) { + x, err := i.getNumber(xv) if err != nil { return nil, err } - y, err := i.getNumber(yv, trace) + y, err := i.getNumber(yv) if err != nil { return nil, err } if y.value == 0 { - return nil, i.Error("Division by zero.", trace) + return nil, i.Error("Division by zero.") } - return makeDoubleCheck(i, trace, math.Mod(x.value, y.value)) + return makeDoubleCheck(i, math.Mod(x.value, y.value)) } -func valueCmp(i *interpreter, trace traceElement, x, y value) (int, error) { +func valueCmp(i *interpreter, x, y value) (int, error) { switch left := x.(type) { case *valueNumber: - right, err := i.getNumber(y, trace) + right, err := i.getNumber(y) if err != nil { return 0, err } return float64Cmp(left.value, right.value), nil case valueString: - right, err := i.getString(y, trace) + right, err := i.getString(y) if err != nil { return 0, err } return stringCmp(left, right), nil case *valueArray: - right, err := i.getArray(y, trace) + right, err := i.getArray(y) if err != nil { return 0, err } - return arrayCmp(i, trace, left, right) + return arrayCmp(i, left, right) default: - return 0, i.typeErrorGeneral(x, trace) + return 0, i.typeErrorGeneral(x) } } -func arrayCmp(i *interpreter, trace traceElement, x, y *valueArray) (int, error) { +func arrayCmp(i *interpreter, x, y *valueArray) (int, error) { for index := 0; index < minInt(x.length(), y.length()); index++ { - left, err := x.index(i, trace, index) + left, err := x.index(i, index) if err != nil { return 0, err } - right, err := y.index(i, trace, index) + right, err := y.index(i, index) if err != nil { return 0, err } - cmp, err := valueCmp(i, trace, left, right) + cmp, err := valueCmp(i, left, right) if err != nil { return 0, err } @@ -176,39 +176,39 @@ func arrayCmp(i *interpreter, trace traceElement, x, y *valueArray) (int, error) return intCmp(x.length(), y.length()), nil } -func builtinLess(i *interpreter, trace traceElement, x, y value) (value, error) { - r, err := valueCmp(i, trace, x, y) +func builtinLess(i *interpreter, x, y value) (value, error) { + r, err := valueCmp(i, x, y) if err != nil { return nil, err } return makeValueBoolean(r == -1), nil } -func builtinGreater(i *interpreter, trace traceElement, x, y value) (value, error) { - r, err := valueCmp(i, trace, x, y) +func builtinGreater(i *interpreter, x, y value) (value, error) { + r, err := valueCmp(i, x, y) if err != nil { return nil, err } return makeValueBoolean(r == 1), nil } -func builtinGreaterEq(i *interpreter, trace traceElement, x, y value) (value, error) { - r, err := valueCmp(i, trace, x, y) +func builtinGreaterEq(i *interpreter, x, y value) (value, error) { + r, err := valueCmp(i, x, y) if err != nil { return nil, err } return makeValueBoolean(r >= 0), nil } -func builtinLessEq(i *interpreter, trace traceElement, x, y value) (value, error) { - r, err := valueCmp(i, trace, x, y) +func builtinLessEq(i *interpreter, x, y value) (value, error) { + r, err := valueCmp(i, x, y) if err != nil { return nil, err } return makeValueBoolean(r <= 0), nil } -func builtinLength(i *interpreter, trace traceElement, x value) (value, error) { +func builtinLength(i *interpreter, x value) (value, error) { var num int switch x := x.(type) { case *valueObject: @@ -224,29 +224,30 @@ func builtinLength(i *interpreter, trace traceElement, x value) (value, error) { } } default: - return nil, i.typeErrorGeneral(x, trace) + return nil, i.typeErrorGeneral(x) } return makeValueNumber(float64(num)), nil } -func builtinToString(i *interpreter, trace traceElement, x value) (value, error) { +func builtinToString(i *interpreter, x value) (value, error) { switch x := x.(type) { case valueString: return x, nil } var buf bytes.Buffer - err := i.manifestAndSerializeJSON(&buf, trace, x, false, "") + err := i.manifestAndSerializeJSON(&buf, x, false, "") if err != nil { return nil, err } return makeValueString(buf.String()), nil } -func builtinTrace(i *interpreter, trace traceElement, x value, y value) (value, error) { - xStr, err := i.getString(x, trace) +func builtinTrace(i *interpreter, x value, y value) (value, error) { + xStr, err := i.getString(x) if err != nil { return nil, err } + trace := i.stack.currentTrace filename := trace.loc.FileName line := trace.loc.Begin.Line fmt.Fprintf( @@ -264,12 +265,12 @@ type astMakeArrayElement struct { index int } -func builtinMakeArray(i *interpreter, trace traceElement, szv, funcv value) (value, error) { - sz, err := i.getInt(szv, trace) +func builtinMakeArray(i *interpreter, szv, funcv value) (value, error) { + sz, err := i.getInt(szv) if err != nil { return nil, err } - fun, err := i.getFunction(funcv, trace) + fun, err := i.getFunction(funcv) if err != nil { return nil, err } @@ -288,8 +289,8 @@ func builtinMakeArray(i *interpreter, trace traceElement, szv, funcv value) (val return makeValueArray(elems), nil } -func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (value, error) { - fun, err := i.getFunction(funcv, trace) +func builtinFlatMap(i *interpreter, funcv, arrv value) (value, error) { + fun, err := i.getFunction(funcv) if err != nil { return nil, err } @@ -301,11 +302,11 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu // TODO(sbarzowski) verify that it actually helps elems := make([]*cachedThunk, 0, num) for counter := 0; counter < num; counter++ { - returnedValue, err := fun.call(i, trace, args(arrv.elements[counter])) + returnedValue, err := fun.call(i, args(arrv.elements[counter])) if err != nil { return nil, err } - returned, err := i.getArray(returnedValue, trace) + returned, err := i.getArray(returnedValue) if err != nil { return nil, err } @@ -315,11 +316,11 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu case valueString: var str strings.Builder for _, elem := range arrv.getRunes() { - returnedValue, err := fun.call(i, trace, args(readyThunk(makeValueString(string(elem))))) + returnedValue, err := fun.call(i, args(readyThunk(makeValueString(string(elem))))) if err != nil { return nil, err } - returned, err := i.getString(returnedValue, trace) + returned, err := i.getString(returnedValue) if err != nil { return nil, err } @@ -327,15 +328,15 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu } return makeValueString(str.String()), nil default: - return nil, i.Error("std.flatMap second param must be array / string, got "+arrv.getType().name, trace) + return nil, i.Error("std.flatMap second param must be array / string, got " + arrv.getType().name) } } -func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueArray) (value, error) { +func joinArrays(i *interpreter, sep *valueArray, arr *valueArray) (value, error) { result := make([]*cachedThunk, 0, arr.length()) first := true for _, elem := range arr.elements { - elemValue, err := i.evaluatePV(elem, trace) + elemValue, err := i.evaluatePV(elem) if err != nil { return nil, err } @@ -348,7 +349,7 @@ func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueA } result = append(result, v.elements...) default: - return nil, i.typeErrorSpecific(elemValue, &valueArray{}, trace) + return nil, i.typeErrorSpecific(elemValue, &valueArray{}) } first = false @@ -356,11 +357,11 @@ func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueA return makeValueArray(result), nil } -func joinStrings(i *interpreter, trace traceElement, sep valueString, arr *valueArray) (value, error) { +func joinStrings(i *interpreter, sep valueString, arr *valueArray) (value, error) { result := make([]rune, 0, arr.length()) first := true for _, elem := range arr.elements { - elemValue, err := i.evaluatePV(elem, trace) + elemValue, err := i.evaluatePV(elem) if err != nil { return nil, err } @@ -373,30 +374,30 @@ func joinStrings(i *interpreter, trace traceElement, sep valueString, arr *value } result = append(result, v.getRunes()...) default: - return nil, i.typeErrorSpecific(elemValue, emptyString(), trace) + return nil, i.typeErrorSpecific(elemValue, emptyString()) } first = false } return makeStringFromRunes(result), nil } -func builtinJoin(i *interpreter, trace traceElement, sep, arrv value) (value, error) { - arr, err := i.getArray(arrv, trace) +func builtinJoin(i *interpreter, sep, arrv value) (value, error) { + arr, err := i.getArray(arrv) if err != nil { return nil, err } switch sep := sep.(type) { case valueString: - return joinStrings(i, trace, sep, arr) + return joinStrings(i, sep, arr) case *valueArray: - return joinArrays(i, trace, sep, arr) + return joinArrays(i, sep, arr) default: - return nil, i.Error("join first parameter should be string or array, got "+sep.getType().name, trace) + return nil, i.Error("join first parameter should be string or array, got " + sep.getType().name) } } -func builtinReverse(i *interpreter, trace traceElement, arrv value) (value, error) { - arr, err := i.getArray(arrv, trace) +func builtinReverse(i *interpreter, arrv value) (value, error) { + arr, err := i.getArray(arrv) if err != nil { return nil, err } @@ -412,12 +413,12 @@ func builtinReverse(i *interpreter, trace traceElement, arrv value) (value, erro return makeValueArray(reversedArray), nil } -func builtinFilter(i *interpreter, trace traceElement, funcv, arrv value) (value, error) { - arr, err := i.getArray(arrv, trace) +func builtinFilter(i *interpreter, funcv, arrv value) (value, error) { + arr, err := i.getArray(arrv) if err != nil { return nil, err } - fun, err := i.getFunction(funcv, trace) + fun, err := i.getFunction(funcv) if err != nil { return nil, err } @@ -427,11 +428,11 @@ func builtinFilter(i *interpreter, trace traceElement, funcv, arrv value) (value // TODO(sbarzowski) verify that it actually helps elems := make([]*cachedThunk, 0, num) for counter := 0; counter < num; counter++ { - includedValue, err := fun.call(i, trace, args(arr.elements[counter])) + includedValue, err := fun.call(i, args(arr.elements[counter])) if err != nil { return nil, err } - included, err := i.getBoolean(includedValue, trace) + included, err := i.getBoolean(includedValue) if err != nil { return nil, err } @@ -444,7 +445,6 @@ func builtinFilter(i *interpreter, trace traceElement, funcv, arrv value) (value type sortData struct { i *interpreter - trace traceElement thunks []*cachedThunk keys []value err error @@ -455,7 +455,7 @@ func (d *sortData) Len() int { } func (d *sortData) Less(i, j int) bool { - r, err := valueCmp(d.i, d.trace, d.keys[i], d.keys[j]) + r, err := valueCmp(d.i, d.keys[i], d.keys[j]) if err != nil { d.err = err panic("Error while comparing elements") @@ -480,26 +480,26 @@ func (d *sortData) Sort() (err error) { return } -func builtinSort(i *interpreter, trace traceElement, arguments []value) (value, error) { +func builtinSort(i *interpreter, arguments []value) (value, error) { arrv := arguments[0] keyFv := arguments[1] - arr, err := i.getArray(arrv, trace) + arr, err := i.getArray(arrv) if err != nil { return nil, err } - keyF, err := i.getFunction(keyFv, trace) + keyF, err := i.getFunction(keyFv) if err != nil { return nil, err } num := arr.length() - data := sortData{i: i, trace: trace, thunks: make([]*cachedThunk, num), keys: make([]value, num)} + data := sortData{i: i, thunks: make([]*cachedThunk, num), keys: make([]value, num)} for counter := 0; counter < num; counter++ { var err error data.thunks[counter] = arr.elements[counter] - data.keys[counter], err = keyF.call(i, trace, args(arr.elements[counter])) + data.keys[counter], err = keyF.call(i, args(arr.elements[counter])) if err != nil { return nil, err } @@ -513,12 +513,12 @@ func builtinSort(i *interpreter, trace traceElement, arguments []value) (value, return makeValueArray(data.thunks), nil } -func builtinRange(i *interpreter, trace traceElement, fromv, tov value) (value, error) { - from, err := i.getInt(fromv, trace) +func builtinRange(i *interpreter, fromv, tov value) (value, error) { + from, err := i.getInt(fromv) if err != nil { return nil, err } - to, err := i.getInt(tov, trace) + to, err := i.getInt(tov) if err != nil { return nil, err } @@ -529,16 +529,16 @@ func builtinRange(i *interpreter, trace traceElement, fromv, tov value) (value, return makeValueArray(elems), nil } -func builtinNegation(i *interpreter, trace traceElement, x value) (value, error) { - b, err := i.getBoolean(x, trace) +func builtinNegation(i *interpreter, x value) (value, error) { + b, err := i.getBoolean(x) if err != nil { return nil, err } return makeValueBoolean(!b.value), nil } -func builtinBitNeg(i *interpreter, trace traceElement, x value) (value, error) { - n, err := i.getNumber(x, trace) +func builtinBitNeg(i *interpreter, x value) (value, error) { + n, err := i.getNumber(x) if err != nil { return nil, err } @@ -546,12 +546,12 @@ func builtinBitNeg(i *interpreter, trace traceElement, x value) (value, error) { return int64ToValue(^intValue), nil } -func builtinIdentity(i *interpreter, trace traceElement, x value) (value, error) { +func builtinIdentity(i *interpreter, x value) (value, error) { return x, nil } -func builtinUnaryPlus(i *interpreter, trace traceElement, x value) (value, error) { - n, err := i.getNumber(x, trace) +func builtinUnaryPlus(i *interpreter, x value) (value, error) { + n, err := i.getNumber(x) if err != nil { return nil, err } @@ -559,8 +559,8 @@ func builtinUnaryPlus(i *interpreter, trace traceElement, x value) (value, error return makeValueNumber(n.value), nil } -func builtinUnaryMinus(i *interpreter, trace traceElement, x value) (value, error) { - n, err := i.getNumber(x, trace) +func builtinUnaryMinus(i *interpreter, x value) (value, error) { + n, err := i.getNumber(x) if err != nil { return nil, err } @@ -569,25 +569,25 @@ func builtinUnaryMinus(i *interpreter, trace traceElement, x value) (value, erro // TODO(sbarzowski) since we have a builtin implementation of equals it's no longer really // needed and we should deprecate it eventually -func primitiveEquals(i *interpreter, trace traceElement, x, y value) (value, error) { +func primitiveEquals(i *interpreter, x, y value) (value, error) { if x.getType() != y.getType() { return makeValueBoolean(false), nil } switch left := x.(type) { case *valueBoolean: - right, err := i.getBoolean(y, trace) + right, err := i.getBoolean(y) if err != nil { return nil, err } return makeValueBoolean(left.value == right.value), nil case *valueNumber: - right, err := i.getNumber(y, trace) + right, err := i.getNumber(y) if err != nil { return nil, err } return makeValueBoolean(left.value == right.value), nil case valueString: - right, err := i.getString(y, trace) + right, err := i.getString(y) if err != nil { return nil, err } @@ -595,34 +595,33 @@ func primitiveEquals(i *interpreter, trace traceElement, x, y value) (value, err case *valueNull: return makeValueBoolean(true), nil case *valueFunction: - return nil, i.Error("Cannot test equality of functions", trace) + return nil, i.Error("Cannot test equality of functions") default: return nil, i.Error( - "primitiveEquals operates on primitive types, got "+x.getType().name, - trace, + "primitiveEquals operates on primitive types, got " + x.getType().name, ) } } -func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { +func rawEquals(i *interpreter, x, y value) (bool, error) { if x.getType() != y.getType() { return false, nil } switch left := x.(type) { case *valueBoolean: - right, err := i.getBoolean(y, trace) + right, err := i.getBoolean(y) if err != nil { return false, err } return left.value == right.value, nil case *valueNumber: - right, err := i.getNumber(y, trace) + right, err := i.getNumber(y) if err != nil { return false, err } return left.value == right.value, nil case valueString: - right, err := i.getString(y, trace) + right, err := i.getString(y) if err != nil { return false, err } @@ -630,7 +629,7 @@ func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { case *valueNull: return true, nil case *valueArray: - right, err := i.getArray(y, trace) + right, err := i.getArray(y) if err != nil { return false, err } @@ -638,15 +637,15 @@ func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { return false, nil } for j := range left.elements { - leftElem, err := i.evaluatePV(left.elements[j], trace) + leftElem, err := i.evaluatePV(left.elements[j]) if err != nil { return false, err } - rightElem, err := i.evaluatePV(right.elements[j], trace) + rightElem, err := i.evaluatePV(right.elements[j]) if err != nil { return false, err } - eq, err := rawEquals(i, trace, leftElem, rightElem) + eq, err := rawEquals(i, leftElem, rightElem) if err != nil { return false, err } @@ -656,7 +655,7 @@ func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { } return true, nil case *valueObject: - right, err := i.getObject(y, trace) + right, err := i.getObject(y) if err != nil { return false, err } @@ -674,15 +673,15 @@ func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { } for j := range leftFields { fieldName := leftFields[j] - leftField, err := left.index(i, trace, fieldName) + leftField, err := left.index(i, fieldName) if err != nil { return false, err } - rightField, err := right.index(i, trace, fieldName) + rightField, err := right.index(i, fieldName) if err != nil { return false, err } - eq, err := rawEquals(i, trace, leftField, rightField) + eq, err := rawEquals(i, leftField, rightField) if err != nil { return false, err } @@ -692,33 +691,33 @@ func rawEquals(i *interpreter, trace traceElement, x, y value) (bool, error) { } return true, nil case *valueFunction: - return false, i.Error("Cannot test equality of functions", trace) + return false, i.Error("Cannot test equality of functions") } panic(fmt.Sprintf("Unhandled case in equals %#+v %#+v", x, y)) } -func builtinEquals(i *interpreter, trace traceElement, x, y value) (value, error) { - eq, err := rawEquals(i, trace, x, y) +func builtinEquals(i *interpreter, x, y value) (value, error) { + eq, err := rawEquals(i, x, y) if err != nil { return nil, err } return makeValueBoolean(eq), nil } -func builtinNotEquals(i *interpreter, trace traceElement, x, y value) (value, error) { - eq, err := rawEquals(i, trace, x, y) +func builtinNotEquals(i *interpreter, x, y value) (value, error) { + eq, err := rawEquals(i, x, y) if err != nil { return nil, err } return makeValueBoolean(!eq), nil } -func builtinType(i *interpreter, trace traceElement, x value) (value, error) { +func builtinType(i *interpreter, x value) (value, error) { return makeValueString(x.getType().name), nil } -func builtinMd5(i *interpreter, trace traceElement, x value) (value, error) { - str, err := i.getString(x, trace) +func builtinMd5(i *interpreter, x value) (value, error) { + str, err := i.getString(x) if err != nil { return nil, err } @@ -726,7 +725,7 @@ func builtinMd5(i *interpreter, trace traceElement, x value) (value, error) { return makeValueString(hex.EncodeToString(hash[:])), nil } -func builtinBase64(i *interpreter, trace traceElement, input value) (value, error) { +func builtinBase64(i *interpreter, input value) (value, error) { var byteArr []byte var sanityCheck = func(v int) (string, bool) { @@ -740,7 +739,7 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro switch input.(type) { case valueString: - vStr, err := i.getString(input, trace) + vStr, err := i.getString(input) if err != nil { return nil, err } @@ -750,47 +749,47 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro n := int(r) msg, ok := sanityCheck(n) if !ok { - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } } byteArr = []byte(str) case *valueArray: - vArr, err := i.getArray(input, trace) + vArr, err := i.getArray(input) if err != nil { return nil, err } for _, cThunk := range vArr.elements { - cTv, err := cThunk.getValue(i, trace) + cTv, err := cThunk.getValue(i) if err != nil { return nil, err } - vInt, err := i.getInt(cTv, trace) + vInt, err := i.getInt(cTv) if err != nil { msg := fmt.Sprintf("base64 encountered a non-integer value in the array, got %s", cTv.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } msg, ok := sanityCheck(vInt) if !ok { - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } byteArr = append(byteArr, byte(vInt)) } default: msg := fmt.Sprintf("base64 can only base64 encode strings / arrays of single bytes, got %s", input.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } sEnc := base64.StdEncoding.EncodeToString(byteArr) return makeValueString(sEnc), nil } -func builtinEncodeUTF8(i *interpreter, trace traceElement, x value) (value, error) { - str, err := i.getString(x, trace) +func builtinEncodeUTF8(i *interpreter, x value) (value, error) { + str, err := i.getString(x) if err != nil { return nil, err } @@ -802,19 +801,19 @@ func builtinEncodeUTF8(i *interpreter, trace traceElement, x value) (value, erro return makeValueArray(elems), nil } -func builtinDecodeUTF8(i *interpreter, trace traceElement, x value) (value, error) { - arr, err := i.getArray(x, trace) +func builtinDecodeUTF8(i *interpreter, x value) (value, error) { + arr, err := i.getArray(x) if err != nil { return nil, err } bs := make([]byte, len(arr.elements)) // it will be longer if characters fall outside of ASCII for pos := range arr.elements { - v, err := i.evaluateInt(arr.elements[pos], trace) + v, err := i.evaluateInt(arr.elements[pos]) if err != nil { return nil, err } if v < 0 || v > 255 { - return nil, i.Error(fmt.Sprintf("Bytes must be integers in range [0, 255], got %d", v), trace) + return nil, i.Error(fmt.Sprintf("Bytes must be integers in range [0, 255], got %d", v)) } bs[pos] = byte(v) } @@ -825,47 +824,47 @@ func builtinDecodeUTF8(i *interpreter, trace traceElement, x value) (value, erro // https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology const codepointMax = 0x10FFFF -func builtinChar(i *interpreter, trace traceElement, x value) (value, error) { - n, err := i.getNumber(x, trace) +func builtinChar(i *interpreter, x value) (value, error) { + n, err := i.getNumber(x) if err != nil { return nil, err } if n.value > codepointMax { - return nil, i.Error(fmt.Sprintf("Invalid unicode codepoint, got %v", n.value), trace) + return nil, i.Error(fmt.Sprintf("Invalid unicode codepoint, got %v", n.value)) } else if n.value < 0 { - return nil, i.Error(fmt.Sprintf("Codepoints must be >= 0, got %v", n.value), trace) + return nil, i.Error(fmt.Sprintf("Codepoints must be >= 0, got %v", n.value)) } return makeValueString(string(rune(n.value))), nil } -func builtinCodepoint(i *interpreter, trace traceElement, x value) (value, error) { - str, err := i.getString(x, trace) +func builtinCodepoint(i *interpreter, x value) (value, error) { + str, err := i.getString(x) if err != nil { return nil, err } if str.length() != 1 { - return nil, i.Error(fmt.Sprintf("codepoint takes a string of length 1, got length %v", str.length()), trace) + return nil, i.Error(fmt.Sprintf("codepoint takes a string of length 1, got length %v", str.length())) } return makeValueNumber(float64(str.getRunes()[0])), nil } -func makeDoubleCheck(i *interpreter, trace traceElement, x float64) (value, error) { +func makeDoubleCheck(i *interpreter, x float64) (value, error) { if math.IsNaN(x) { - return nil, i.Error("Not a number", trace) + return nil, i.Error("Not a number") } if math.IsInf(x, 0) { - return nil, i.Error("Overflow", trace) + return nil, i.Error("Overflow") } return makeValueNumber(x), nil } -func liftNumeric(f func(float64) float64) func(*interpreter, traceElement, value) (value, error) { - return func(i *interpreter, trace traceElement, x value) (value, error) { - n, err := i.getNumber(x, trace) +func liftNumeric(f func(float64) float64) func(*interpreter, value) (value, error) { + return func(i *interpreter, x value) (value, error) { + n, err := i.getNumber(x) if err != nil { return nil, err } - return makeDoubleCheck(i, trace, f(n.value)) + return makeDoubleCheck(i, f(n.value)) } } @@ -895,28 +894,28 @@ var builtinExponent = liftNumeric(func(f float64) float64 { return float64(exponent) }) -func liftBitwise(f func(int64, int64) int64, positiveRightArg bool) func(*interpreter, traceElement, value, value) (value, error) { - return func(i *interpreter, trace traceElement, xv, yv value) (value, error) { - x, err := i.getNumber(xv, trace) +func liftBitwise(f func(int64, int64) int64, positiveRightArg bool) func(*interpreter, value, value) (value, error) { + return func(i *interpreter, xv, yv value) (value, error) { + x, err := i.getNumber(xv) if err != nil { return nil, err } - y, err := i.getNumber(yv, trace) + y, err := i.getNumber(yv) if err != nil { return nil, err } if x.value < math.MinInt64 || x.value > math.MaxInt64 { msg := fmt.Sprintf("Bitwise operator argument %v outside of range [%v, %v]", x.value, int64(math.MinInt64), int64(math.MaxInt64)) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } if y.value < math.MinInt64 || y.value > math.MaxInt64 { msg := fmt.Sprintf("Bitwise operator argument %v outside of range [%v, %v]", y.value, int64(math.MinInt64), int64(math.MaxInt64)) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } if positiveRightArg && y.value < 0 { - return nil, makeRuntimeError("Shift by negative exponent.", i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError("Shift by negative exponent.", i.getCurrentStackTrace()) } - return makeDoubleCheck(i, trace, float64(f(int64(x.value), int64(y.value)))) + return makeDoubleCheck(i, float64(f(int64(x.value), int64(y.value)))) } } @@ -926,12 +925,12 @@ var builtinBitwiseAnd = liftBitwise(func(x, y int64) int64 { return x & y }, fal var builtinBitwiseOr = liftBitwise(func(x, y int64) int64 { return x | y }, false) var builtinBitwiseXor = liftBitwise(func(x, y int64) int64 { return x ^ y }, false) -func builtinObjectFieldsEx(i *interpreter, trace traceElement, objv, includeHiddenV value) (value, error) { - obj, err := i.getObject(objv, trace) +func builtinObjectFieldsEx(i *interpreter, objv, includeHiddenV value) (value, error) { + obj, err := i.getObject(objv) if err != nil { return nil, err } - includeHidden, err := i.getBoolean(includeHiddenV, trace) + includeHidden, err := i.getBoolean(includeHiddenV) if err != nil { return nil, err } @@ -944,16 +943,16 @@ func builtinObjectFieldsEx(i *interpreter, trace traceElement, objv, includeHidd return makeValueArray(elems), nil } -func builtinObjectHasEx(i *interpreter, trace traceElement, objv value, fnamev value, includeHiddenV value) (value, error) { - obj, err := i.getObject(objv, trace) +func builtinObjectHasEx(i *interpreter, objv value, fnamev value, includeHiddenV value) (value, error) { + obj, err := i.getObject(objv) if err != nil { return nil, err } - fname, err := i.getString(fnamev, trace) + fname, err := i.getString(fnamev) if err != nil { return nil, err } - includeHidden, err := i.getBoolean(includeHiddenV, trace) + includeHidden, err := i.getBoolean(includeHiddenV) if err != nil { return nil, err } @@ -962,52 +961,52 @@ func builtinObjectHasEx(i *interpreter, trace traceElement, objv value, fnamev v return makeValueBoolean(hasField), nil } -func builtinPow(i *interpreter, trace traceElement, basev value, expv value) (value, error) { - base, err := i.getNumber(basev, trace) +func builtinPow(i *interpreter, basev value, expv value) (value, error) { + base, err := i.getNumber(basev) if err != nil { return nil, err } - exp, err := i.getNumber(expv, trace) + exp, err := i.getNumber(expv) if err != nil { return nil, err } - return makeDoubleCheck(i, trace, math.Pow(base.value, exp.value)) + return makeDoubleCheck(i, math.Pow(base.value, exp.value)) } -func builtinSubstr(i *interpreter, trace traceElement, inputStr, inputFrom, inputLen value) (value, error) { - strV, err := i.getString(inputStr, trace) +func builtinSubstr(i *interpreter, inputStr, inputFrom, inputLen value) (value, error) { + strV, err := i.getString(inputStr) if err != nil { msg := fmt.Sprintf("substr first parameter should be a string, got %s", inputStr.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } - fromV, err := i.getNumber(inputFrom, trace) + fromV, err := i.getNumber(inputFrom) if err != nil { msg := fmt.Sprintf("substr second parameter should be a number, got %s", inputFrom.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } if math.Mod(fromV.value, 1) != 0 { msg := fmt.Sprintf("substr second parameter should be an integer, got %f", fromV.value) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } - lenV, err := i.getNumber(inputLen, trace) + lenV, err := i.getNumber(inputLen) if err != nil { msg := fmt.Sprintf("substr third parameter should be a number, got %s", inputLen.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } - lenInt, err := i.getInt(lenV, trace) + lenInt, err := i.getInt(lenV) if err != nil { msg := fmt.Sprintf("substr third parameter should be an integer, got %f", lenV.value) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } if lenInt < 0 { msg := fmt.Sprintf("substr third parameter should be greater than zero, got %d", lenInt) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } fromInt := int(fromV.value) @@ -1027,26 +1026,26 @@ func builtinSubstr(i *interpreter, trace traceElement, inputStr, inputFrom, inpu return makeValueString(string(runes[fromInt:endIndex])), nil } -func builtinSplitLimit(i *interpreter, trace traceElement, strv, cv, maxSplitsV value) (value, error) { - str, err := i.getString(strv, trace) +func builtinSplitLimit(i *interpreter, strv, cv, maxSplitsV value) (value, error) { + str, err := i.getString(strv) if err != nil { return nil, err } - c, err := i.getString(cv, trace) + c, err := i.getString(cv) if err != nil { return nil, err } - maxSplits, err := i.getInt(maxSplitsV, trace) + maxSplits, err := i.getInt(maxSplitsV) if err != nil { return nil, err } if maxSplits < -1 { - return nil, i.Error(fmt.Sprintf("std.splitLimit third parameter should be -1 or non-negative, got %v", maxSplits), trace) + return nil, i.Error(fmt.Sprintf("std.splitLimit third parameter should be -1 or non-negative, got %v", maxSplits)) } sStr := str.getGoString() sC := c.getGoString() if len(sC) != 1 { - return nil, i.Error(fmt.Sprintf("std.splitLimit second parameter should have length 1, got %v", len(sC)), trace) + return nil, i.Error(fmt.Sprintf("std.splitLimit second parameter should have length 1, got %v", len(sC))) } // the convention is slightly different from strings.splitN in Go (the meaning of non-negative values is shifted by one) @@ -1064,16 +1063,16 @@ func builtinSplitLimit(i *interpreter, trace traceElement, strv, cv, maxSplitsV return makeValueArray(res), nil } -func builtinStrReplace(i *interpreter, trace traceElement, strv, fromv, tov value) (value, error) { - str, err := i.getString(strv, trace) +func builtinStrReplace(i *interpreter, strv, fromv, tov value) (value, error) { + str, err := i.getString(strv) if err != nil { return nil, err } - from, err := i.getString(fromv, trace) + from, err := i.getString(fromv) if err != nil { return nil, err } - to, err := i.getString(tov, trace) + to, err := i.getString(tov) if err != nil { return nil, err } @@ -1081,34 +1080,34 @@ func builtinStrReplace(i *interpreter, trace traceElement, strv, fromv, tov valu sFrom := from.getGoString() sTo := to.getGoString() if len(sFrom) == 0 { - return nil, i.Error("'from' string must not be zero length.", trace) + return nil, i.Error("'from' string must not be zero length.") } return makeValueString(strings.Replace(sStr, sFrom, sTo, -1)), nil } -func base64DecodeGoBytes(i *interpreter, trace traceElement, str string) ([]byte, error) { +func base64DecodeGoBytes(i *interpreter, str string) ([]byte, error) { strLen := len(str) if strLen%4 != 0 { msg := fmt.Sprintf("input string appears not to be a base64 encoded string. Wrong length found (%d)", strLen) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } decodedBytes, err := base64.StdEncoding.DecodeString(str) if err != nil { - return nil, i.Error(fmt.Sprintf("failed to decode: %s", err), trace) + return nil, i.Error(fmt.Sprintf("failed to decode: %s", err)) } return decodedBytes, nil } -func builtinBase64DecodeBytes(i *interpreter, trace traceElement, input value) (value, error) { - vStr, err := i.getString(input, trace) +func builtinBase64DecodeBytes(i *interpreter, input value) (value, error) { + vStr, err := i.getString(input) if err != nil { msg := fmt.Sprintf("base64DecodeBytes requires a string, got %s", input.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } - decodedBytes, err := base64DecodeGoBytes(i, trace, vStr.getGoString()) + decodedBytes, err := base64DecodeGoBytes(i, vStr.getGoString()) if err != nil { return nil, err } @@ -1121,14 +1120,14 @@ func builtinBase64DecodeBytes(i *interpreter, trace traceElement, input value) ( return makeValueArray(res), nil } -func builtinBase64Decode(i *interpreter, trace traceElement, input value) (value, error) { - vStr, err := i.getString(input, trace) +func builtinBase64Decode(i *interpreter, input value) (value, error) { + vStr, err := i.getString(input) if err != nil { msg := fmt.Sprintf("base64DecodeBytes requires a string, got %s", input.getType().name) - return nil, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError(msg, i.getCurrentStackTrace()) } - decodedBytes, err := base64DecodeGoBytes(i, trace, vStr.getGoString()) + decodedBytes, err := base64DecodeGoBytes(i, vStr.getGoString()) if err != nil { return nil, err } @@ -1136,17 +1135,17 @@ func builtinBase64Decode(i *interpreter, trace traceElement, input value) (value return makeValueString(string(decodedBytes)), nil } -func builtinUglyObjectFlatMerge(i *interpreter, trace traceElement, x value) (value, error) { +func builtinUglyObjectFlatMerge(i *interpreter, x value) (value, error) { // TODO(sbarzowski) consider keeping comprehensions in AST // It will probably be way less hacky, with better error messages and better performance - objarr, err := i.getArray(x, trace) + objarr, err := i.getArray(x) if err != nil { return nil, err } newFields := make(simpleObjectFieldMap) for _, elem := range objarr.elements { - obj, err := i.evaluateObject(elem, trace) + obj, err := i.evaluateObject(elem) if err != nil { return nil, err } @@ -1161,7 +1160,7 @@ func builtinUglyObjectFlatMerge(i *interpreter, trace traceElement, x value) (va // there is only one field, really for fieldName, fieldVal := range simpleObj.fields { if _, alreadyExists := newFields[fieldName]; alreadyExists { - return nil, i.Error(duplicateFieldNameErrMsg(fieldName), trace) + return nil, i.Error(duplicateFieldNameErrMsg(fieldName)) } newFields[fieldName] = simpleObjectField{ @@ -1182,8 +1181,8 @@ func builtinUglyObjectFlatMerge(i *interpreter, trace traceElement, x value) (va ), nil } -func builtinParseJSON(i *interpreter, trace traceElement, str value) (value, error) { - sval, err := i.getString(str, trace) +func builtinParseJSON(i *interpreter, str value) (value, error) { + sval, err := i.getString(str) if err != nil { return nil, err } @@ -1191,9 +1190,9 @@ func builtinParseJSON(i *interpreter, trace traceElement, str value) (value, err var parsedJSON interface{} err = json.Unmarshal([]byte(s), &parsedJSON) if err != nil { - return nil, i.Error(fmt.Sprintf("failed to parse JSON: %v", err.Error()), trace) + return nil, i.Error(fmt.Sprintf("failed to parse JSON: %v", err.Error())) } - return jsonToValue(i, trace, parsedJSON) + return jsonToValue(i, parsedJSON) } func jsonEncode(v interface{}) (string, error) { @@ -1212,8 +1211,8 @@ func jsonEncode(v interface{}) (string, error) { // These should ideally be unified // For backwards compatibility reasons, we are manually marshalling to json so we can control formatting // In the future, it might be apt to use a library [pretty-printing] function -func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value) (value, error) { - vindent, err := i.getString(indent, trace) +func builtinManifestJSONEx(i *interpreter, obj, indent value) (value, error) { + vindent, err := i.getString(indent) if err != nil { return nil, err } @@ -1235,7 +1234,7 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value case valueString: jStr, err := jsonEncode(v.getGoString()) if err != nil { - return "", i.Error(fmt.Sprintf("failed to marshal valueString to JSON: %v", err.Error()), trace) + return "", i.Error(fmt.Sprintf("failed to marshal valueString to JSON: %v", err.Error())) } return jStr, nil case *valueNumber: @@ -1243,14 +1242,14 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value case *valueBoolean: return fmt.Sprintf("%t", v.value), nil case *valueFunction: - return "", i.Error(fmt.Sprintf("tried to manifest function at %s", path), trace) + return "", i.Error(fmt.Sprintf("tried to manifest function at %s", path)) case *valueArray: newIndent := cindent + sindent lines := []string{"[\n"} var arrayLines []string for aI, cThunk := range v.elements { - cTv, err := cThunk.getValue(i, trace) + cTv, err := cThunk.getValue(i) if err != nil { return "", err } @@ -1273,14 +1272,14 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value sort.Strings(fields) var objectLines []string for _, fieldName := range fields { - fieldValue, err := v.index(i, trace, fieldName) + fieldValue, err := v.index(i, fieldName) if err != nil { return "", err } fieldNameMarshalled, err := jsonEncode(fieldName) if err != nil { - return "", i.Error(fmt.Sprintf("failed to marshal object fieldname to JSON: %v", err.Error()), trace) + return "", i.Error(fmt.Sprintf("failed to marshal object fieldname to JSON: %v", err.Error())) } newPath := append(path, fieldName) @@ -1296,7 +1295,7 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value lines = append(lines, "\n"+cindent+"}") return strings.Join(lines, ""), nil default: - return "", i.Error(fmt.Sprintf("unknown type to marshal to JSON: %s", reflect.TypeOf(v)), trace) + return "", i.Error(fmt.Sprintf("unknown type to marshal to JSON: %s", reflect.TypeOf(v))) } } @@ -1308,20 +1307,20 @@ func builtinManifestJSONEx(i *interpreter, trace traceElement, obj, indent value return makeValueString(finalString), nil } -func builtinExtVar(i *interpreter, trace traceElement, name value) (value, error) { - str, err := i.getString(name, trace) +func builtinExtVar(i *interpreter, name value) (value, error) { + str, err := i.getString(name) if err != nil { return nil, err } index := str.getGoString() if pv, ok := i.extVars[index]; ok { - return i.evaluatePV(pv, trace) + return i.evaluatePV(pv) } - return nil, i.Error("Undefined external variable: "+string(index), trace) + return nil, i.Error("Undefined external variable: " + string(index)) } -func builtinNative(i *interpreter, trace traceElement, name value) (value, error) { - str, err := i.getString(name, trace) +func builtinNative(i *interpreter, name value) (value, error) { + str, err := i.getString(name) if err != nil { return nil, err } @@ -1362,7 +1361,7 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value) return flatArgs } -type unaryBuiltinFunc func(*interpreter, traceElement, value) (value, error) +type unaryBuiltinFunc func(*interpreter, value) (value, error) type unaryBuiltin struct { name ast.Identifier @@ -1370,19 +1369,14 @@ type unaryBuiltin struct { params ast.Identifiers } -func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement { - context := "builtin function <" + string(name) + ">" - return traceElement{loc: trace.loc, context: &context} -} - -func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { +func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) { flatArgs := flattenArgs(args, b.parameters(), []value{}) - builtinTrace := getBuiltinTrace(trace, b.name) - x, err := flatArgs[0].getValue(i, trace) + + x, err := flatArgs[0].getValue(i) if err != nil { return nil, err } - return b.function(i, builtinTrace, x) + return b.function(i, x) } func (b *unaryBuiltin) parameters() []namedParameter { @@ -1397,7 +1391,7 @@ func (b *unaryBuiltin) Name() ast.Identifier { return b.name } -type binaryBuiltinFunc func(*interpreter, traceElement, value, value) (value, error) +type binaryBuiltinFunc func(*interpreter, value, value) (value, error) type binaryBuiltin struct { name ast.Identifier @@ -1405,18 +1399,18 @@ type binaryBuiltin struct { params ast.Identifiers } -func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { +func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) { flatArgs := flattenArgs(args, b.parameters(), []value{}) - builtinTrace := getBuiltinTrace(trace, b.name) - x, err := flatArgs[0].getValue(i, trace) + + x, err := flatArgs[0].getValue(i) if err != nil { return nil, err } - y, err := flatArgs[1].getValue(i, trace) + y, err := flatArgs[1].getValue(i) if err != nil { return nil, err } - return b.function(i, builtinTrace, x, y) + return b.function(i, x, y) } func (b *binaryBuiltin) parameters() []namedParameter { @@ -1431,7 +1425,7 @@ func (b *binaryBuiltin) Name() ast.Identifier { return b.name } -type ternaryBuiltinFunc func(*interpreter, traceElement, value, value, value) (value, error) +type ternaryBuiltinFunc func(*interpreter, value, value, value) (value, error) type ternaryBuiltin struct { name ast.Identifier @@ -1439,22 +1433,22 @@ type ternaryBuiltin struct { params ast.Identifiers } -func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { +func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) { flatArgs := flattenArgs(args, b.parameters(), []value{}) - builtinTrace := getBuiltinTrace(trace, b.name) - x, err := flatArgs[0].getValue(i, trace) + + x, err := flatArgs[0].getValue(i) if err != nil { return nil, err } - y, err := flatArgs[1].getValue(i, trace) + y, err := flatArgs[1].getValue(i) if err != nil { return nil, err } - z, err := flatArgs[2].getValue(i, trace) + z, err := flatArgs[2].getValue(i) if err != nil { return nil, err } - return b.function(i, builtinTrace, x, y, z) + return b.function(i, x, y, z) } func (b *ternaryBuiltin) parameters() []namedParameter { @@ -1469,7 +1463,7 @@ func (b *ternaryBuiltin) Name() ast.Identifier { return b.name } -type generalBuiltinFunc func(*interpreter, traceElement, []value) (value, error) +type generalBuiltinFunc func(*interpreter, []value) (value, error) type generalBuiltinParameter struct { name ast.Identifier @@ -1515,18 +1509,17 @@ func (b *generalBuiltin) Name() ast.Identifier { return b.name } -func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) { +func (b *generalBuiltin) evalCall(args callArguments, i *interpreter) (value, error) { flatArgs := flattenArgs(args, b.parameters(), b.defaultValues()) - builtinTrace := getBuiltinTrace(trace, b.name) values := make([]value, len(flatArgs)) for j := 0; j < len(values); j++ { var err error - values[j], err = flatArgs[j].getValue(i, trace) + values[j], err = flatArgs[j].getValue(i) if err != nil { return nil, err } } - return b.function(i, builtinTrace, values) + return b.function(i, values) } // End of builtin utils diff --git a/imports.go b/imports.go index 22a8790..e994e4f 100644 --- a/imports.go +++ b/imports.go @@ -131,10 +131,10 @@ func (cache *importCache) importAST(importedFrom, importedPath string) (ast.Node } // ImportString imports a string, caches it and then returns it. -func (cache *importCache) importString(importedFrom, importedPath string, i *interpreter, trace traceElement) (valueString, error) { +func (cache *importCache) importString(importedFrom, importedPath string, i *interpreter) (valueString, error) { data, _, err := cache.importData(importedFrom, importedPath) if err != nil { - return nil, i.Error(err.Error(), trace) + return nil, i.Error(err.Error()) } return makeValueString(data.String()), nil } @@ -158,10 +158,10 @@ func codeToPV(i *interpreter, filename string, code string) *cachedThunk { } // ImportCode imports code from a path. -func (cache *importCache) importCode(importedFrom, importedPath string, i *interpreter, trace traceElement) (value, error) { +func (cache *importCache) importCode(importedFrom, importedPath string, i *interpreter) (value, error) { node, foundAt, err := cache.importAST(importedFrom, importedPath) if err != nil { - return nil, i.Error(err.Error(), trace) + return nil, i.Error(err.Error()) } var pv potentialValue if cachedPV, isCached := cache.codeCache[foundAt]; !isCached { @@ -176,7 +176,7 @@ func (cache *importCache) importCode(importedFrom, importedPath string, i *inter } else { pv = cachedPV } - return i.evaluatePV(pv, trace) + return i.evaluatePV(pv) } // Concrete importers diff --git a/internal/program/desugarer.go b/internal/program/desugarer.go index 881b53b..2b2c157 100644 --- a/internal/program/desugarer.go +++ b/internal/program/desugarer.go @@ -155,7 +155,7 @@ func buildAnd(left ast.Node, right ast.Node) ast.Node { } // inside is assumed to be already desugared (and cannot be desugared again) -func desugarForSpec(inside ast.Node, forSpec *ast.ForSpec, objLevel int) (ast.Node, error) { +func desugarForSpec(inside ast.Node, loc ast.LocationRange, forSpec *ast.ForSpec, objLevel int) (ast.Node, error) { var body ast.Node if len(forSpec.Conditions) > 0 { cond := forSpec.Conditions[0].Expr @@ -179,11 +179,11 @@ func desugarForSpec(inside ast.Node, forSpec *ast.ForSpec, objLevel int) (ast.No if err != nil { return nil, err } - current := buildStdCall("flatMap", function, forSpec.Expr) + current := buildStdCall("flatMap", loc, function, forSpec.Expr) if forSpec.Outer == nil { return current, nil } - return desugarForSpec(current, forSpec.Outer, objLevel) + return desugarForSpec(current, loc, forSpec.Outer, objLevel) } func wrapInArray(inside ast.Node) ast.Node { @@ -195,7 +195,7 @@ func desugarArrayComp(comp *ast.ArrayComp, objLevel int) (ast.Node, error) { if err != nil { return nil, err } - return desugarForSpec(wrapInArray(comp.Body), &comp.Spec, objLevel) + return desugarForSpec(wrapInArray(comp.Body), *comp.Loc(), &comp.Spec, objLevel) } func desugarObjectComp(comp *ast.ObjectComp, objLevel int) (ast.Node, error) { @@ -222,12 +222,12 @@ func desugarObjectComp(comp *ast.ObjectComp, objLevel int) (ast.Node, error) { panic("Wrong number of fields in object comprehension, it should have been caught during parsing") } - desugaredArrayComp, err := desugarForSpec(wrapInArray(obj), &comp.Spec, objLevel) + desugaredArrayComp, err := desugarForSpec(wrapInArray(obj), *comp.Loc(), &comp.Spec, objLevel) if err != nil { return nil, err } - desugaredComp := buildStdCall("$objectFlatMerge", desugaredArrayComp) + desugaredComp := buildStdCall("$objectFlatMerge", *comp.Loc(), desugaredArrayComp) return desugaredComp, nil } @@ -245,7 +245,7 @@ func buildSimpleIndex(obj ast.Node, member ast.Identifier) ast.Node { } } -func buildStdCall(builtinName ast.Identifier, args ...ast.Node) ast.Node { +func buildStdCall(builtinName ast.Identifier, loc ast.LocationRange, args ...ast.Node) ast.Node { std := &ast.Var{Id: "std"} builtin := buildSimpleIndex(std, builtinName) positional := make([]ast.CommaSeparatedExpr, len(args)) @@ -253,6 +253,9 @@ func buildStdCall(builtinName ast.Identifier, args ...ast.Node) ast.Node { positional[i].Expr = args[i] } return &ast.Apply{ + NodeBase: ast.NodeBase{ + LocRange: loc, + }, Target: builtin, Arguments: ast.Arguments{Positional: positional}, } @@ -350,9 +353,9 @@ func desugar(astPtr *ast.Node, objLevel int) (err error) { if funcname, replaced := desugaredBop[node.Op]; replaced { if node.Op == ast.BopIn { // reversed order of arguments - *astPtr = buildStdCall(funcname, node.Right, node.Left) + *astPtr = buildStdCall(funcname, *node.Loc(), node.Right, node.Left) } else { - *astPtr = buildStdCall(funcname, node.Left, node.Right) + *astPtr = buildStdCall(funcname, *node.Loc(), node.Left, node.Right) } return desugar(astPtr, objLevel) } @@ -455,7 +458,7 @@ func desugar(astPtr *ast.Node, objLevel int) (err error) { if node.Step == nil { node.Step = &ast.LiteralNull{} } - *astPtr = buildStdCall("slice", node.Target, node.BeginIndex, node.EndIndex, node.Step) + *astPtr = buildStdCall("slice", *node.Loc(), node.Target, node.BeginIndex, node.EndIndex, node.Step) err = desugar(astPtr, objLevel) if err != nil { return diff --git a/interpreter.go b/interpreter.go index adfaf97..087223d 100644 --- a/interpreter.go +++ b/interpreter.go @@ -49,15 +49,15 @@ func makeEnvironment(upValues bindingFrame, sb selfBinding) environment { } } -func (i *interpreter) getCurrentStackTrace(additional traceElement) []traceFrame { +func (i *interpreter) getCurrentStackTrace() []traceFrame { var result []traceFrame for _, f := range i.stack.stack { if f.isCall { result = append(result, traceElementToTraceFrame(f.trace)) } } - if additional.loc != nil { - result = append(result, traceElementToTraceFrame(additional)) + if i.stack.currentTrace.loc != nil { + result = append(result, traceElementToTraceFrame(i.stack.currentTrace)) } return result } @@ -95,9 +95,10 @@ func dumpCallFrame(c *callFrame) string { } type callStack struct { - calls int - limit int - stack []*callFrame + calls int + limit int + stack []*callFrame + currentTrace traceElement } func dumpCallStack(c *callStack) string { @@ -123,6 +124,7 @@ func (s *callStack) popIfExists(whichFrame int) { if s.top().isCall { s.calls-- } + s.setCurrentTrace(s.stack[len(s.stack)-1].trace) s.stack = s.stack[:len(s.stack)-1] } } @@ -142,6 +144,17 @@ func (s *callStack) tailCallTrimStack() { } } +func (s *callStack) setCurrentTrace(trace traceElement) { + if s.currentTrace != (traceElement{}) { + panic("Tried to change the traceElement while the old one was still there.") + } + s.currentTrace = trace +} + +func (s *callStack) clearCurrentTrace() { + s.currentTrace = traceElement{} +} + type tailCallStatus int const ( @@ -149,20 +162,26 @@ const ( tailCall ) -func (s *callStack) newCall(trace traceElement, env environment, trimmable bool) { +func (s *callStack) newCall(env environment, trimmable bool) { + if s.currentTrace == (traceElement{}) { + panic("Saving empty traceElement on stack") + } s.stack = append(s.stack, &callFrame{ isCall: true, - trace: trace, + trace: s.currentTrace, env: env, trimmable: trimmable, }) + s.clearCurrentTrace() s.calls++ } func (s *callStack) newLocal(vars bindingFrame) { s.stack = append(s.stack, &callFrame{ - env: makeEnvironment(vars, selfBinding{}), + env: makeEnvironment(vars, selfBinding{}), + trace: s.currentTrace, }) + s.clearCurrentTrace() } // getSelfBinding resolves the self construct @@ -256,12 +275,12 @@ func addBindings(a, b bindingFrame) bindingFrame { return result } -func (i *interpreter) newCall(trace traceElement, env environment, trimmable bool) error { +func (i *interpreter) newCall(env environment, trimmable bool) error { s := &i.stack if s.calls >= s.limit { - return makeRuntimeError("max stack frames exceeded.", i.getCurrentStackTrace(trace)) + return makeRuntimeError("max stack frames exceeded.", i.getCurrentStackTrace()) } - s.newCall(trace, env, trimmable) + s.newCall(env, trimmable) return nil } @@ -270,6 +289,10 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { loc: a.Loc(), context: a.Context(), } + oldTrace := i.stack.currentTrace + i.stack.clearCurrentTrace() + i.stack.setCurrentTrace(trace) + defer func() { i.stack.clearCurrentTrace(); i.stack.setCurrentTrace(oldTrace) }() switch node := a.(type) { case *ast.Array: @@ -289,7 +312,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { if err != nil { return nil, err } - x, err := i.getBoolean(xv, trace) + x, err := i.getBoolean(xv) if err != nil { return nil, err } @@ -300,14 +323,14 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { if err != nil { return nil, err } - return i.getBoolean(yv, trace) + return i.getBoolean(yv) } else if node.Op == ast.BopOr { // Special case for shortcut semantics. xv, err := i.evaluate(node.Left, nonTailCall) if err != nil { return nil, err } - x, err := i.getBoolean(xv, trace) + x, err := i.getBoolean(xv) if err != nil { return nil, err } @@ -318,7 +341,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { if err != nil { return nil, err } - return i.getBoolean(yv, trace) + return i.getBoolean(yv) } else { left, err := i.evaluate(node.Left, nonTailCall) @@ -331,7 +354,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { } // TODO(dcunnin): The double dereference here is probably not necessary. builtin := bopBuiltins[node.Op] - return builtin.function(i, trace, left, right) + return builtin.function(i, left, right) } case *ast.Unary: @@ -342,7 +365,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { builtin := uopBuiltins[node.Op] - result, err := builtin.function(i, trace, value) + result, err := builtin.function(i, value) if err != nil { return nil, err } @@ -353,7 +376,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { if err != nil { return nil, err } - condBool, err := i.getBoolean(cond, trace) + condBool, err := i.getBoolean(cond) if err != nil { return nil, err } @@ -378,11 +401,11 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { // Omitted field. continue default: - return nil, i.Error(fmt.Sprintf("Field name must be string, got %v", fieldNameValue.getType().name), trace) + return nil, i.Error(fmt.Sprintf("Field name must be string, got %v", fieldNameValue.getType().name)) } if _, ok := fields[fieldName]; ok { - return nil, i.Error(duplicateFieldNameErrMsg(fieldName), trace) + return nil, i.Error(duplicateFieldNameErrMsg(fieldName)) } var f unboundField = &codeUnboundField{field.Body} if field.PlusSuper { @@ -408,16 +431,16 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { return nil, err } if msgVal.getType() != stringType { - msgVal, err = builtinToString(i, trace, msgVal) + msgVal, err = builtinToString(i, msgVal) if err != nil { return nil, err } } - msg, err := i.getString(msgVal, trace) + msg, err := i.getString(msgVal) if err != nil { return nil, err } - return nil, i.Error(msg.getGoString(), trace) + return nil, i.Error(msg.getGoString()) case *ast.Index: targetValue, err := i.evaluate(node.Target, nonTailCall) @@ -430,37 +453,37 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { } switch target := targetValue.(type) { case *valueObject: - indexString, err := i.getString(index, trace) + indexString, err := i.getString(index) if err != nil { return nil, err } - return target.index(i, trace, indexString.getGoString()) + return target.index(i, indexString.getGoString()) case *valueArray: - indexInt, err := i.getNumber(index, trace) + indexInt, err := i.getNumber(index) if err != nil { return nil, err } // TODO(https://github.com/google/jsonnet/issues/377): non-integer indexes should be an error - return target.index(i, trace, int(indexInt.value)) + return target.index(i, int(indexInt.value)) case valueString: - indexInt, err := i.getNumber(index, trace) + indexInt, err := i.getNumber(index) if err != nil { return nil, err } // TODO(https://github.com/google/jsonnet/issues/377): non-integer indexes should be an error - return target.index(i, trace, int(indexInt.value)) + return target.index(i, int(indexInt.value)) } - return nil, i.Error(fmt.Sprintf("Value non indexable: %v", reflect.TypeOf(targetValue)), trace) + return nil, i.Error(fmt.Sprintf("Value non indexable: %v", reflect.TypeOf(targetValue))) case *ast.Import: codePath := node.Loc().FileName - return i.importCache.importCode(codePath, node.File.Value, i, trace) + return i.importCache.importCode(codePath, node.File.Value, i) case *ast.ImportStr: codePath := node.Loc().FileName - return i.importCache.importString(codePath, node.File.Value, i, trace) + return i.importCache.importString(codePath, node.File.Value, i) case *ast.LiteralBoolean: return makeValueBoolean(node.Value), nil @@ -474,7 +497,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("overflow", trace) + return nil, i.Error("overflow") } return makeValueNumber(num), nil @@ -506,25 +529,25 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { case *ast.Var: foo := i.stack.lookUpVarOrPanic(node.Id) - return foo.getValue(i, trace) + return foo.getValue(i) case *ast.SuperIndex: index, err := i.evaluate(node.Index, nonTailCall) if err != nil { return nil, err } - indexStr, err := i.getString(index, trace) + indexStr, err := i.getString(index) if err != nil { return nil, err } - return objectIndex(i, trace, i.stack.getSelfBinding().super(), indexStr.getGoString()) + return objectIndex(i, i.stack.getSelfBinding().super(), indexStr.getGoString()) case *ast.InSuper: index, err := i.evaluate(node.Index, nonTailCall) if err != nil { return nil, err } - indexStr, err := i.getString(index, trace) + indexStr, err := i.getString(index) if err != nil { return nil, err } @@ -542,7 +565,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { if err != nil { return nil, err } - function, err := i.getFunction(target, trace) + function, err := i.getFunction(target) if err != nil { return nil, err } @@ -561,7 +584,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { for i, arg := range node.Arguments.Named { arguments.named[i] = namedCallArgument{name: arg.Name, pv: &cachedThunk{env: &argEnv, body: arg.Arg}} } - return i.evaluateTailCall(function, arguments, tc, trace) + return i.evaluateTailCall(function, arguments, tc) case *astMakeArrayElement: arguments := callArguments{ @@ -571,7 +594,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) { }, }, } - return i.evaluateTailCall(node.function, arguments, tc, trace) + return i.evaluateTailCall(node.function, arguments, tc) default: panic(fmt.Sprintf("Executing this AST type not implemented: %v", reflect.TypeOf(a))) @@ -624,14 +647,20 @@ func unparseNumber(v float64) string { } // manifestJSON converts to standard JSON representation as in "encoding/json" package -func (i *interpreter) manifestJSON(trace traceElement, v value) (interface{}, error) { +func (i *interpreter) manifestJSON(v value) (interface{}, error) { + // TODO(sbarzowski) Add nice stack traces indicating the part of the code which + // evaluates to non-manifestable value (that might require passing context about + // the root value) + if i.stack.currentTrace == (traceElement{}) { + panic("manifesting JSON with empty traceElement") + } switch v := v.(type) { case *valueBoolean: return v.value, nil case *valueFunction: - return nil, makeRuntimeError("couldn't manifest function in JSON output.", i.getCurrentStackTrace(trace)) + return nil, makeRuntimeError("couldn't manifest function as JSON", i.getCurrentStackTrace()) case *valueNumber: return v.value, nil @@ -645,11 +674,11 @@ func (i *interpreter) manifestJSON(trace traceElement, v value) (interface{}, er case *valueArray: result := make([]interface{}, 0, len(v.elements)) for _, th := range v.elements { - elVal, err := i.evaluatePV(th, trace) + elVal, err := i.evaluatePV(th) if err != nil { return nil, err } - elem, err := i.manifestJSON(trace, elVal) + elem, err := i.manifestJSON(elVal) if err != nil { return nil, err } @@ -661,7 +690,7 @@ func (i *interpreter) manifestJSON(trace traceElement, v value) (interface{}, er fieldNames := objectFields(v, withoutHidden) sort.Strings(fieldNames) - err := checkAssertions(i, trace, v) + err := checkAssertions(i, v) if err != nil { return nil, err } @@ -669,12 +698,12 @@ func (i *interpreter) manifestJSON(trace traceElement, v value) (interface{}, er result := make(map[string]interface{}) for _, fieldName := range fieldNames { - fieldVal, err := v.index(i, trace, fieldName) + fieldVal, err := v.index(i, fieldName) if err != nil { return nil, err } - field, err := i.manifestJSON(trace, fieldVal) + field, err := i.manifestJSON(fieldVal) if err != nil { return nil, err } @@ -686,7 +715,7 @@ func (i *interpreter) manifestJSON(trace traceElement, v value) (interface{}, er default: return nil, makeRuntimeError( fmt.Sprintf("manifesting this value not implemented yet: %s", reflect.TypeOf(v)), - i.getCurrentStackTrace(trace), + i.getCurrentStackTrace(), ) } @@ -790,8 +819,8 @@ func serializeJSON(v interface{}, multiline bool, indent string, buf *bytes.Buff } func (i *interpreter) manifestAndSerializeJSON( - buf *bytes.Buffer, trace traceElement, v value, multiline bool, indent string) error { - manifested, err := i.manifestJSON(trace, v) + buf *bytes.Buffer, v value, multiline bool, indent string) error { + manifested, err := i.manifestJSON(v) if err != nil { return err } @@ -800,19 +829,19 @@ func (i *interpreter) manifestAndSerializeJSON( } // manifestString expects the value to be a string and returns it. -func (i *interpreter) manifestString(buf *bytes.Buffer, trace traceElement, v value) error { +func (i *interpreter) manifestString(buf *bytes.Buffer, v value) error { switch v := v.(type) { case valueString: buf.WriteString(v.getGoString()) return nil default: - return makeRuntimeError(fmt.Sprintf("expected string result, got: %s", v.getType().name), i.getCurrentStackTrace(trace)) + return makeRuntimeError(fmt.Sprintf("expected string result, got: %s", v.getType().name), i.getCurrentStackTrace()) } } -func (i *interpreter) manifestAndSerializeMulti(trace traceElement, v value, stringOutputMode bool) (r map[string]string, err error) { +func (i *interpreter) manifestAndSerializeMulti(v value, stringOutputMode bool) (r map[string]string, err error) { r = make(map[string]string) - json, err := i.manifestJSON(trace, v) + json, err := i.manifestJSON(v) if err != nil { return r, err } @@ -826,7 +855,7 @@ func (i *interpreter) manifestAndSerializeMulti(trace traceElement, v value, str default: msg := fmt.Sprintf("multi mode: top-level object's key %s has a value of type %T, "+ "should be a string", filename, val) - return r, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return r, makeRuntimeError(msg, i.getCurrentStackTrace()) } } else { var buf bytes.Buffer @@ -839,14 +868,14 @@ func (i *interpreter) manifestAndSerializeMulti(trace traceElement, v value, str msg := fmt.Sprintf("multi mode: top-level object was a %s, "+ "should be an object whose keys are filenames and values hold "+ "the JSON for that file.", v.getType().name) - return r, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return r, makeRuntimeError(msg, i.getCurrentStackTrace()) } return } -func (i *interpreter) manifestAndSerializeYAMLStream(trace traceElement, v value) (r []string, err error) { +func (i *interpreter) manifestAndSerializeYAMLStream(v value) (r []string, err error) { r = make([]string, 0) - json, err := i.manifestJSON(trace, v) + json, err := i.manifestJSON(v) if err != nil { return r, err } @@ -862,12 +891,12 @@ func (i *interpreter) manifestAndSerializeYAMLStream(trace traceElement, v value msg := fmt.Sprintf("stream mode: top-level object was a %s, "+ "should be an array whose elements hold "+ "the JSON for each document in the stream.", v.getType().name) - return r, makeRuntimeError(msg, i.getCurrentStackTrace(trace)) + return r, makeRuntimeError(msg, i.getCurrentStackTrace()) } return } -func jsonToValue(i *interpreter, trace traceElement, v interface{}) (value, error) { +func jsonToValue(i *interpreter, v interface{}) (value, error) { switch v := v.(type) { case nil: return &nullValue, nil @@ -875,7 +904,7 @@ func jsonToValue(i *interpreter, trace traceElement, v interface{}) (value, erro case []interface{}: elems := make([]*cachedThunk, len(v)) for counter, elem := range v { - val, err := jsonToValue(i, trace, elem) + val, err := jsonToValue(i, elem) if err != nil { return nil, err } @@ -886,12 +915,12 @@ func jsonToValue(i *interpreter, trace traceElement, v interface{}) (value, erro case bool: return makeValueBoolean(v), nil case float64: - return makeDoubleCheck(i, trace, v) + return makeDoubleCheck(i, v) case map[string]interface{}: fieldMap := map[string]value{} for name, f := range v { - val, err := jsonToValue(i, trace, f) + val, err := jsonToValue(i, f) if err != nil { return nil, err } @@ -903,12 +932,12 @@ func jsonToValue(i *interpreter, trace traceElement, v interface{}) (value, erro return makeValueString(v), nil default: - return nil, i.Error(fmt.Sprintf("Not a json type: %#+v", v), trace) + return nil, i.Error(fmt.Sprintf("Not a json type: %#+v", v)) } } -func (i *interpreter) EvalInCleanEnv(fromWhere traceElement, env *environment, ast ast.Node, trimmable bool) (value, error) { - err := i.newCall(fromWhere, *env, trimmable) +func (i *interpreter) EvalInCleanEnv(env *environment, ast ast.Node, trimmable bool) (value, error) { + err := i.newCall(*env, trimmable) if err != nil { return nil, err } @@ -921,56 +950,54 @@ func (i *interpreter) EvalInCleanEnv(fromWhere traceElement, env *environment, a return val, err } -func (i *interpreter) evaluatePV(ph potentialValue, trace traceElement) (value, error) { - return ph.getValue(i, trace) +func (i *interpreter) evaluatePV(ph potentialValue) (value, error) { + return ph.getValue(i) } -func (i *interpreter) evaluateTailCall(function *valueFunction, args callArguments, tc tailCallStatus, trace traceElement) (value, error) { +func (i *interpreter) evaluateTailCall(function *valueFunction, args callArguments, tc tailCallStatus) (value, error) { if tc == tailCall { i.stack.tailCallTrimStack() } - return function.call(i, trace, args) + return function.call(i, args) } -func (i *interpreter) Error(s string, trace traceElement) error { - err := makeRuntimeError(s, i.getCurrentStackTrace(trace)) +func (i *interpreter) Error(s string) error { + err := makeRuntimeError(s, i.getCurrentStackTrace()) return err } -func (i *interpreter) typeErrorSpecific(bad value, good value, trace traceElement) error { +func (i *interpreter) typeErrorSpecific(bad value, good value) error { return i.Error( fmt.Sprintf("Unexpected type %v, expected %v", bad.getType().name, good.getType().name), - trace, ) } -func (i *interpreter) typeErrorGeneral(bad value, trace traceElement) error { +func (i *interpreter) typeErrorGeneral(bad value) error { return i.Error( fmt.Sprintf("Unexpected type %v", bad.getType().name), - trace, ) } -func (i *interpreter) getNumber(val value, trace traceElement) (*valueNumber, error) { +func (i *interpreter) getNumber(val value) (*valueNumber, error) { switch v := val.(type) { case *valueNumber: return v, nil default: - return nil, i.typeErrorSpecific(val, &valueNumber{}, trace) + return nil, i.typeErrorSpecific(val, &valueNumber{}) } } //nolint:unused -func (i *interpreter) evaluateNumber(pv potentialValue, trace traceElement) (*valueNumber, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateNumber(pv potentialValue) (*valueNumber, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getNumber(v, trace) + return i.getNumber(v) } -func (i *interpreter) getInt(val value, trace traceElement) (int, error) { - num, err := i.getNumber(val, trace) +func (i *interpreter) getInt(val value) (int, error) { + num, err := i.getNumber(val) if err != nil { return 0, err } @@ -978,128 +1005,128 @@ func (i *interpreter) getInt(val value, trace traceElement) (int, error) { // on any machine. And it's used only for indexing anyway. intNum := int(int32(num.value)) if float64(intNum) != num.value { - return 0, i.Error(fmt.Sprintf("Expected an integer, but got %v", num.value), trace) + return 0, i.Error(fmt.Sprintf("Expected an integer, but got %v", num.value)) } return intNum, nil } -func (i *interpreter) evaluateInt(pv potentialValue, trace traceElement) (int, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateInt(pv potentialValue) (int, error) { + v, err := i.evaluatePV(pv) if err != nil { return 0, err } - return i.getInt(v, trace) + return i.getInt(v) } //nolint:unused -func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) { - num, err := i.getNumber(val, trace) +func (i *interpreter) getInt64(val value) (int64, error) { + num, err := i.getNumber(val) if err != nil { return 0, err } intNum := int64(num.value) if float64(intNum) != num.value { - return 0, i.Error(fmt.Sprintf("Expected an integer, but got %v", num.value), trace) + return 0, i.Error(fmt.Sprintf("Expected an integer, but got %v", num.value)) } return intNum, nil } //nolint:unused -func (i *interpreter) evaluateInt64(pv potentialValue, trace traceElement) (int64, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateInt64(pv potentialValue) (int64, error) { + v, err := i.evaluatePV(pv) if err != nil { return 0, err } - return i.getInt64(v, trace) + return i.getInt64(v) } -func (i *interpreter) getString(val value, trace traceElement) (valueString, error) { +func (i *interpreter) getString(val value) (valueString, error) { switch v := val.(type) { case valueString: return v, nil default: - return nil, i.typeErrorSpecific(val, emptyString(), trace) + return nil, i.typeErrorSpecific(val, emptyString()) } } //nolint:unused -func (i *interpreter) evaluateString(pv potentialValue, trace traceElement) (valueString, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateString(pv potentialValue) (valueString, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getString(v, trace) + return i.getString(v) } -func (i *interpreter) getBoolean(val value, trace traceElement) (*valueBoolean, error) { +func (i *interpreter) getBoolean(val value) (*valueBoolean, error) { switch v := val.(type) { case *valueBoolean: return v, nil default: - return nil, i.typeErrorSpecific(val, &valueBoolean{}, trace) + return nil, i.typeErrorSpecific(val, &valueBoolean{}) } } //nolint:unused -func (i *interpreter) evaluateBoolean(pv potentialValue, trace traceElement) (*valueBoolean, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateBoolean(pv potentialValue) (*valueBoolean, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getBoolean(v, trace) + return i.getBoolean(v) } -func (i *interpreter) getArray(val value, trace traceElement) (*valueArray, error) { +func (i *interpreter) getArray(val value) (*valueArray, error) { switch v := val.(type) { case *valueArray: return v, nil default: - return nil, i.typeErrorSpecific(val, &valueArray{}, trace) + return nil, i.typeErrorSpecific(val, &valueArray{}) } } //nolint:unused -func (i *interpreter) evaluateArray(pv potentialValue, trace traceElement) (*valueArray, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateArray(pv potentialValue) (*valueArray, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getArray(v, trace) + return i.getArray(v) } -func (i *interpreter) getFunction(val value, trace traceElement) (*valueFunction, error) { +func (i *interpreter) getFunction(val value) (*valueFunction, error) { switch v := val.(type) { case *valueFunction: return v, nil default: - return nil, i.typeErrorSpecific(val, &valueFunction{}, trace) + return nil, i.typeErrorSpecific(val, &valueFunction{}) } } //nolint:unused -func (i *interpreter) evaluateFunction(pv potentialValue, trace traceElement) (*valueFunction, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateFunction(pv potentialValue) (*valueFunction, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getFunction(v, trace) + return i.getFunction(v) } -func (i *interpreter) getObject(val value, trace traceElement) (*valueObject, error) { +func (i *interpreter) getObject(val value) (*valueObject, error) { switch v := val.(type) { case *valueObject: return v, nil default: - return nil, i.typeErrorSpecific(val, &valueObject{}, trace) + return nil, i.typeErrorSpecific(val, &valueObject{}) } } -func (i *interpreter) evaluateObject(pv potentialValue, trace traceElement) (*valueObject, error) { - v, err := i.evaluatePV(pv, trace) +func (i *interpreter) evaluateObject(pv potentialValue) (*valueObject, error) { + v, err := i.evaluatePV(pv) if err != nil { return nil, err } - return i.getObject(v, trace) + return i.getObject(v) } func buildStdObject(i *interpreter) (*valueObject, error) { @@ -1128,7 +1155,9 @@ func evaluateStd(i *interpreter) (value, error) { evalLoc := ast.MakeLocationRangeMessage("During evaluation of std") evalTrace := traceElement{loc: &evalLoc} node := astgen.StdAst - return i.EvalInCleanEnv(evalTrace, &beforeStdEnv, node, false) + i.stack.setCurrentTrace(evalTrace) + defer i.stack.clearCurrentTrace() + return i.EvalInCleanEnv(&beforeStdEnv, node, false) } func prepareExtVars(i *interpreter, ext vmExtMap, kind string) map[string]*cachedThunk { @@ -1188,7 +1217,9 @@ func evaluateAux(i *interpreter, node ast.Node, tla vmExtMap) (value, traceEleme loc: &evalLoc, } env := makeInitialEnv(node.Loc().FileName, i.baseStd) - result, err := i.EvalInCleanEnv(evalTrace, &env, node, false) + i.stack.setCurrentTrace(evalTrace) + result, err := i.EvalInCleanEnv(&env, node, false) + i.stack.clearCurrentTrace() if err != nil { return nil, traceElement{}, err } @@ -1199,11 +1230,13 @@ func evaluateAux(i *interpreter, node ast.Node, tla vmExtMap) (value, traceEleme for argName, pv := range toplevelArgMap { args.named = append(args.named, namedCallArgument{name: ast.Identifier(argName), pv: pv}) } - funcLoc := ast.MakeLocationRangeMessage("Top-level function") + funcLoc := ast.MakeLocationRangeMessage("Top-level function call") funcTrace := traceElement{ loc: &funcLoc, } - result, err = f.call(i, funcTrace, args) + i.stack.setCurrentTrace(funcTrace) + result, err = f.call(i, args) + i.stack.clearCurrentTrace() if err != nil { return nil, traceElement{}, err } @@ -1230,11 +1263,13 @@ func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string] } var buf bytes.Buffer + i.stack.setCurrentTrace(manifestationTrace) if stringOutputMode { - err = i.manifestString(&buf, manifestationTrace, result) + err = i.manifestString(&buf, result) } else { - err = i.manifestAndSerializeJSON(&buf, manifestationTrace, result, true, "") + err = i.manifestAndSerializeJSON(&buf, result, true, "") } + i.stack.clearCurrentTrace() if err != nil { return "", err } @@ -1256,7 +1291,10 @@ func evaluateMulti(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[st return nil, err } - return i.manifestAndSerializeMulti(manifestationTrace, result, stringOutputMode) + i.stack.setCurrentTrace(manifestationTrace) + manifested, err := i.manifestAndSerializeMulti(result, stringOutputMode) + i.stack.clearCurrentTrace() + return manifested, err } // TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead @@ -1273,5 +1311,8 @@ func evaluateStream(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[s return nil, err } - return i.manifestAndSerializeYAMLStream(manifestationTrace, result) + i.stack.setCurrentTrace(manifestationTrace) + manifested, err := i.manifestAndSerializeYAMLStream(result) + i.stack.clearCurrentTrace() + return manifested, err } diff --git a/testdata/array_comp_try_iterate_over_obj.golden b/testdata/array_comp_try_iterate_over_obj.golden new file mode 100644 index 0000000..123943f --- /dev/null +++ b/testdata/array_comp_try_iterate_over_obj.golden @@ -0,0 +1,10 @@ +RUNTIME ERROR: std.flatMap second param must be array / string, got object +------------------------------------------------- + testdata/array_comp_try_iterate_over_obj:1:1-16 + +[a for a in {}] + +------------------------------------------------- + During evaluation + + diff --git a/testdata/array_comp_try_iterate_over_obj.jsonnet b/testdata/array_comp_try_iterate_over_obj.jsonnet new file mode 100644 index 0000000..b722e5a --- /dev/null +++ b/testdata/array_comp_try_iterate_over_obj.jsonnet @@ -0,0 +1 @@ +[a for a in {}] diff --git a/testdata/array_comp_try_iterate_over_obj.linter.golden b/testdata/array_comp_try_iterate_over_obj.linter.golden new file mode 100644 index 0000000..e69de29 diff --git a/testdata/arrcomp_if6.golden b/testdata/arrcomp_if6.golden index 9883de0..786f3fd 100644 --- a/testdata/arrcomp_if6.golden +++ b/testdata/arrcomp_if6.golden @@ -5,7 +5,9 @@ RUNTIME ERROR: x [x for x in [1] if error "x"] ------------------------------------------------- - builtin function + testdata/arrcomp_if6:1:1-30 + +[x for x in [1] if error "x"] ------------------------------------------------- During evaluation diff --git a/testdata/arrcomp_if7.golden b/testdata/arrcomp_if7.golden index 9b5cb5e..6bd2e72 100644 --- a/testdata/arrcomp_if7.golden +++ b/testdata/arrcomp_if7.golden @@ -3,7 +3,9 @@ RUNTIME ERROR: Unexpected type number, expected boolean ------------------------------------------------- - builtin function + testdata/arrcomp_if7:1:1-29 + +[x for x in [1, 2, 3] if 42] ------------------------------------------------- During evaluation diff --git a/testdata/builtinBase64DecodeBytes_high_codepoint.golden b/testdata/builtinBase64DecodeBytes_high_codepoint.golden index 9d1334c..a9fff3d 100644 --- a/testdata/builtinBase64DecodeBytes_high_codepoint.golden +++ b/testdata/builtinBase64DecodeBytes_high_codepoint.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: failed to decode: illegal base64 data at input byte 0 ------------------------------------------------- - testdata/builtinBase64DecodeBytes_high_codepoint:1:1-30 builtin function + testdata/builtinBase64DecodeBytes_high_codepoint:1:1-30 $ std.base64DecodeBytes("ĀQ=") diff --git a/testdata/builtinBase64DecodeBytes_invalid_base64_data.golden b/testdata/builtinBase64DecodeBytes_invalid_base64_data.golden index 3aa23a5..2c9bd23 100644 --- a/testdata/builtinBase64DecodeBytes_invalid_base64_data.golden +++ b/testdata/builtinBase64DecodeBytes_invalid_base64_data.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: input string appears not to be a base64 encoded string. Wrong length found (5) ------------------------------------------------- - testdata/builtinBase64DecodeBytes_invalid_base64_data:1:1-31 builtin function + testdata/builtinBase64DecodeBytes_invalid_base64_data:1:1-31 $ std.base64DecodeBytes("wrong") diff --git a/testdata/builtinBase64DecodeBytes_wrong_type.golden b/testdata/builtinBase64DecodeBytes_wrong_type.golden index c81c79d..037acc4 100644 --- a/testdata/builtinBase64DecodeBytes_wrong_type.golden +++ b/testdata/builtinBase64DecodeBytes_wrong_type.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64DecodeBytes requires a string, got number ------------------------------------------------- - testdata/builtinBase64DecodeBytes_wrong_type:1:1-25 builtin function + testdata/builtinBase64DecodeBytes_wrong_type:1:1-25 $ std.base64DecodeBytes(1) diff --git a/testdata/builtinBase64Decode_high_codepoint.golden b/testdata/builtinBase64Decode_high_codepoint.golden index 0e6ddca..8c8bbf7 100644 --- a/testdata/builtinBase64Decode_high_codepoint.golden +++ b/testdata/builtinBase64Decode_high_codepoint.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: failed to decode: illegal base64 data at input byte 0 ------------------------------------------------- - testdata/builtinBase64Decode_high_codepoint:1:1-25 builtin function + testdata/builtinBase64Decode_high_codepoint:1:1-25 $ std.base64Decode("ĀQ=") diff --git a/testdata/builtinBase64Decode_invalid_base64_data.golden b/testdata/builtinBase64Decode_invalid_base64_data.golden index 1bdd793..e20254e 100644 --- a/testdata/builtinBase64Decode_invalid_base64_data.golden +++ b/testdata/builtinBase64Decode_invalid_base64_data.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: input string appears not to be a base64 encoded string. Wrong length found (5) ------------------------------------------------- - testdata/builtinBase64Decode_invalid_base64_data:1:1-26 builtin function + testdata/builtinBase64Decode_invalid_base64_data:1:1-26 $ std.base64Decode("wrong") diff --git a/testdata/builtinBase64Decode_wrong_type.golden b/testdata/builtinBase64Decode_wrong_type.golden index 9fc81f0..3e9e421 100644 --- a/testdata/builtinBase64Decode_wrong_type.golden +++ b/testdata/builtinBase64Decode_wrong_type.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64DecodeBytes requires a string, got number ------------------------------------------------- - testdata/builtinBase64Decode_wrong_type:1:1-20 builtin function + testdata/builtinBase64Decode_wrong_type:1:1-20 $ std.base64Decode(1) diff --git a/testdata/builtinBase64_invalid_byte_array.golden b/testdata/builtinBase64_invalid_byte_array.golden index 485cafd..d9244be 100644 --- a/testdata/builtinBase64_invalid_byte_array.golden +++ b/testdata/builtinBase64_invalid_byte_array.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64 encountered a non-integer value in the array, got string ------------------------------------------------- - testdata/builtinBase64_invalid_byte_array:1:1-23 builtin function + testdata/builtinBase64_invalid_byte_array:1:1-23 $ std.base64([1, "foo"]) diff --git a/testdata/builtinBase64_invalid_byte_array1.golden b/testdata/builtinBase64_invalid_byte_array1.golden index bed4408..c1ae7fe 100644 --- a/testdata/builtinBase64_invalid_byte_array1.golden +++ b/testdata/builtinBase64_invalid_byte_array1.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64 encountered invalid codepoint value in the array (must be 0 <= X <= 255), got -1 ------------------------------------------------- - testdata/builtinBase64_invalid_byte_array1:1:1-20 builtin function + testdata/builtinBase64_invalid_byte_array1:1:1-20 $ std.base64([1, -1]) diff --git a/testdata/builtinBase64_invalid_byte_array2.golden b/testdata/builtinBase64_invalid_byte_array2.golden index 9c12c9e..539b007 100644 --- a/testdata/builtinBase64_invalid_byte_array2.golden +++ b/testdata/builtinBase64_invalid_byte_array2.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64 encountered invalid codepoint value in the array (must be 0 <= X <= 255), got 256 ------------------------------------------------- - testdata/builtinBase64_invalid_byte_array2:1:1-21 builtin function + testdata/builtinBase64_invalid_byte_array2:1:1-21 $ std.base64([1, 256]) diff --git a/testdata/builtinBase64_non_string_non_array.golden b/testdata/builtinBase64_non_string_non_array.golden index 543470d..dd6decd 100644 --- a/testdata/builtinBase64_non_string_non_array.golden +++ b/testdata/builtinBase64_non_string_non_array.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64 can only base64 encode strings / arrays of single bytes, got number ------------------------------------------------- - testdata/builtinBase64_non_string_non_array:1:1-14 builtin function + testdata/builtinBase64_non_string_non_array:1:1-14 $ std.base64(1) diff --git a/testdata/builtinBase64_string_high_codepoint.golden b/testdata/builtinBase64_string_high_codepoint.golden index 536905b..dd6a750 100644 --- a/testdata/builtinBase64_string_high_codepoint.golden +++ b/testdata/builtinBase64_string_high_codepoint.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: base64 encountered invalid codepoint value in the array (must be 0 <= X <= 255), got 256 ------------------------------------------------- - testdata/builtinBase64_string_high_codepoint:1:1-17 builtin function + testdata/builtinBase64_string_high_codepoint:1:1-17 $ std.base64("Ā") diff --git a/testdata/builtinChar3.golden b/testdata/builtinChar3.golden index 34d2df7..8670ff6 100644 --- a/testdata/builtinChar3.golden +++ b/testdata/builtinChar3.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Codepoints must be >= 0, got -1 ------------------------------------------------- - testdata/builtinChar3:1:1-13 builtin function + testdata/builtinChar3:1:1-13 $ std.char(-1) diff --git a/testdata/builtinChar5.golden b/testdata/builtinChar5.golden index 5e76a1b..c34e65b 100644 --- a/testdata/builtinChar5.golden +++ b/testdata/builtinChar5.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Invalid unicode codepoint, got 1.114112e+06 ------------------------------------------------- - testdata/builtinChar5:2:1-18 builtin function + testdata/builtinChar5:2:1-18 $ std.char(1114112) diff --git a/testdata/builtinChar7.golden b/testdata/builtinChar7.golden index b022ff0..3f38965 100644 --- a/testdata/builtinChar7.golden +++ b/testdata/builtinChar7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/builtinChar7:1:1-16 builtin function + testdata/builtinChar7:1:1-16 $ std.char("xxx") diff --git a/testdata/builtinObjectFieldsEx_bad.golden b/testdata/builtinObjectFieldsEx_bad.golden index d42c5b9..7ea658d 100644 --- a/testdata/builtinObjectFieldsEx_bad.golden +++ b/testdata/builtinObjectFieldsEx_bad.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected object ------------------------------------------------- - testdata/builtinObjectFieldsEx_bad:1:1-29 builtin function + testdata/builtinObjectFieldsEx_bad:1:1-29 $ std.objectFieldsEx(42, true) diff --git a/testdata/builtinObjectFieldsEx_bad2.golden b/testdata/builtinObjectFieldsEx_bad2.golden index f9fe41e..d08698b 100644 --- a/testdata/builtinObjectFieldsEx_bad2.golden +++ b/testdata/builtinObjectFieldsEx_bad2.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected boolean ------------------------------------------------- - testdata/builtinObjectFieldsEx_bad2:1:1-30 builtin function + testdata/builtinObjectFieldsEx_bad2:1:1-30 $ std.objectFieldsEx({}, "xxx") diff --git a/testdata/builtinObjectHasExBadBoolean.golden b/testdata/builtinObjectHasExBadBoolean.golden index 05481a8..d7c2efe 100644 --- a/testdata/builtinObjectHasExBadBoolean.golden +++ b/testdata/builtinObjectHasExBadBoolean.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected boolean ------------------------------------------------- - testdata/builtinObjectHasExBadBoolean:1:1-34 builtin function + testdata/builtinObjectHasExBadBoolean:1:1-34 $ std.objectHasEx({}, "xxx", "xxx") diff --git a/testdata/builtinObjectHasExBadField.golden b/testdata/builtinObjectHasExBadField.golden index 9076a43..a61c4f9 100644 --- a/testdata/builtinObjectHasExBadField.golden +++ b/testdata/builtinObjectHasExBadField.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected string ------------------------------------------------- - testdata/builtinObjectHasExBadField:1:1-31 builtin function + testdata/builtinObjectHasExBadField:1:1-31 $ std.objectHasEx({}, 42, false) diff --git a/testdata/builtinObjectHasExBadObject.golden b/testdata/builtinObjectHasExBadObject.golden index 1d6828e..2953ff3 100644 --- a/testdata/builtinObjectHasExBadObject.golden +++ b/testdata/builtinObjectHasExBadObject.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected object ------------------------------------------------- - testdata/builtinObjectHasExBadObject:1:1-32 builtin function + testdata/builtinObjectHasExBadObject:1:1-32 $ std.objectHasEx(42, "x", false) diff --git a/testdata/builtinReverse_not_array.golden b/testdata/builtinReverse_not_array.golden index 1603ec4..69ee93b 100644 --- a/testdata/builtinReverse_not_array.golden +++ b/testdata/builtinReverse_not_array.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected array ------------------------------------------------- - testdata/builtinReverse_not_array:1:1-20 builtin function + testdata/builtinReverse_not_array:1:1-20 $ std.reverse("asdf") diff --git a/testdata/builtinSubStr_first_param_not_string.golden b/testdata/builtinSubStr_first_param_not_string.golden index 5d55099..53a88df 100644 --- a/testdata/builtinSubStr_first_param_not_string.golden +++ b/testdata/builtinSubStr_first_param_not_string.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr first parameter should be a string, got number ------------------------------------------------- - testdata/builtinSubStr_first_param_not_string:1:1-20 builtin function + testdata/builtinSubStr_first_param_not_string:1:1-20 $ std.substr(1, 0, 1) diff --git a/testdata/builtinSubStr_second_parameter_not_integer.golden b/testdata/builtinSubStr_second_parameter_not_integer.golden index b6cd103..e9677f1 100644 --- a/testdata/builtinSubStr_second_parameter_not_integer.golden +++ b/testdata/builtinSubStr_second_parameter_not_integer.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr second parameter should be an integer, got 1.200000 ------------------------------------------------- - testdata/builtinSubStr_second_parameter_not_integer:1:1-28 builtin function + testdata/builtinSubStr_second_parameter_not_integer:1:1-28 $ std.substr("hello", 1.2, 5) diff --git a/testdata/builtinSubStr_second_parameter_not_number.golden b/testdata/builtinSubStr_second_parameter_not_number.golden index dccc149..0aa5688 100644 --- a/testdata/builtinSubStr_second_parameter_not_number.golden +++ b/testdata/builtinSubStr_second_parameter_not_number.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr second parameter should be a number, got string ------------------------------------------------- - testdata/builtinSubStr_second_parameter_not_number:1:1-30 builtin function + testdata/builtinSubStr_second_parameter_not_number:1:1-30 $ std.substr("hello", "foo", 5) diff --git a/testdata/builtinSubStr_third_parameter_less_then_zero.golden b/testdata/builtinSubStr_third_parameter_less_then_zero.golden index d23e07c..7f3b6bd 100644 --- a/testdata/builtinSubStr_third_parameter_less_then_zero.golden +++ b/testdata/builtinSubStr_third_parameter_less_then_zero.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr third parameter should be greater than zero, got -1 ------------------------------------------------- - testdata/builtinSubStr_third_parameter_less_then_zero:1:1-27 builtin function + testdata/builtinSubStr_third_parameter_less_then_zero:1:1-27 $ std.substr("hello", 0, -1) diff --git a/testdata/builtinSubStr_third_parameter_not_integer.golden b/testdata/builtinSubStr_third_parameter_not_integer.golden index e31d98d..ec65eb3 100644 --- a/testdata/builtinSubStr_third_parameter_not_integer.golden +++ b/testdata/builtinSubStr_third_parameter_not_integer.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr third parameter should be an integer, got 1.200000 ------------------------------------------------- - testdata/builtinSubStr_third_parameter_not_integer:1:1-28 builtin function + testdata/builtinSubStr_third_parameter_not_integer:1:1-28 $ std.substr("hello", 0, 1.2) diff --git a/testdata/builtinSubStr_third_parameter_not_number.golden b/testdata/builtinSubStr_third_parameter_not_number.golden index d7f62be..272531a 100644 --- a/testdata/builtinSubStr_third_parameter_not_number.golden +++ b/testdata/builtinSubStr_third_parameter_not_number.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: substr third parameter should be a number, got string ------------------------------------------------- - testdata/builtinSubStr_third_parameter_not_number:1:1-30 builtin function + testdata/builtinSubStr_third_parameter_not_number:1:1-30 $ std.substr("hello", 0, "foo") diff --git a/testdata/builtin_exp3.golden b/testdata/builtin_exp3.golden index 6a412c8..9d58746 100644 --- a/testdata/builtin_exp3.golden +++ b/testdata/builtin_exp3.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Overflow ------------------------------------------------- - testdata/builtin_exp3:1:1-14 builtin function + testdata/builtin_exp3:1:1-14 $ std.exp(1000) diff --git a/testdata/builtin_exp5.golden b/testdata/builtin_exp5.golden index dd6b5cb..05d9979 100644 --- a/testdata/builtin_exp5.golden +++ b/testdata/builtin_exp5.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Overflow ------------------------------------------------- - testdata/builtin_exp5:1:1-31 builtin function + testdata/builtin_exp5:1:1-31 $ std.exp(100000000000000000000) diff --git a/testdata/builtin_log5.golden b/testdata/builtin_log5.golden index ea35c2e..a1a8701 100644 --- a/testdata/builtin_log5.golden +++ b/testdata/builtin_log5.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Overflow ------------------------------------------------- - testdata/builtin_log5:1:1-11 builtin function + testdata/builtin_log5:1:1-11 $ std.log(0) diff --git a/testdata/builtin_log7.golden b/testdata/builtin_log7.golden index 48dab69..9bbd4d7 100644 --- a/testdata/builtin_log7.golden +++ b/testdata/builtin_log7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Not a number ------------------------------------------------- - testdata/builtin_log7:1:1-12 builtin function + testdata/builtin_log7:1:1-12 $ std.log(-1) diff --git a/testdata/builtin_log8.golden b/testdata/builtin_log8.golden index ee1b084..da53e5e 100644 --- a/testdata/builtin_log8.golden +++ b/testdata/builtin_log8.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Not a number ------------------------------------------------- - testdata/builtin_log8:1:1-24 builtin function + testdata/builtin_log8:1:1-24 $ std.log(-1000000000000) diff --git a/testdata/builtin_sqrt2.golden b/testdata/builtin_sqrt2.golden index 448be2d..05e5d63 100644 --- a/testdata/builtin_sqrt2.golden +++ b/testdata/builtin_sqrt2.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/builtin_sqrt2:1:1-19 builtin function + testdata/builtin_sqrt2:1:1-19 $ std.sqrt("cookie") diff --git a/testdata/cpp-tests-override/ext3.golden.stderr b/testdata/cpp-tests-override/ext3.golden.stderr new file mode 100644 index 0000000..6d4e1af --- /dev/null +++ b/testdata/cpp-tests-override/ext3.golden.stderr @@ -0,0 +1,4 @@ +RUNTIME ERROR: Undefined external variable: x + :1:1-16 $ + During evaluation + diff --git a/testdata/cpp-tests-override/tla3.golden.stderr b/testdata/cpp-tests-override/tla3.golden.stderr new file mode 100644 index 0000000..0e8e8b2 --- /dev/null +++ b/testdata/cpp-tests-override/tla3.golden.stderr @@ -0,0 +1,3 @@ +RUNTIME ERROR: function has no parameter y + Top-level function call + diff --git a/testdata/cpp-tests-override/tla7.golden.stderr b/testdata/cpp-tests-override/tla7.golden.stderr new file mode 100644 index 0000000..f99ff6d --- /dev/null +++ b/testdata/cpp-tests-override/tla7.golden.stderr @@ -0,0 +1,3 @@ +RUNTIME ERROR: function has no parameter x + Top-level function call + diff --git a/testdata/error_function_fail.golden b/testdata/error_function_fail.golden index 3149552..cba92ce 100644 --- a/testdata/error_function_fail.golden +++ b/testdata/error_function_fail.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: couldn't manifest function in JSON output. +RUNTIME ERROR: couldn't manifest function as JSON ------------------------------------------------- testdata/error_function_fail:1:1-23 $ diff --git a/testdata/extvar_error.golden b/testdata/extvar_error.golden index 62b923e..9d16a75 100644 --- a/testdata/extvar_error.golden +++ b/testdata/extvar_error.golden @@ -5,7 +5,7 @@ RUNTIME ERROR: xxx error 'xxx' ------------------------------------------------- - testdata/extvar_error:1:1-23 builtin function + testdata/extvar_error:1:1-23 $ std.extVar("errorVar") diff --git a/testdata/extvar_not_a_string.golden b/testdata/extvar_not_a_string.golden index f85c2cb..a42869b 100644 --- a/testdata/extvar_not_a_string.golden +++ b/testdata/extvar_not_a_string.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected string ------------------------------------------------- - testdata/extvar_not_a_string:1:1-15 builtin function + testdata/extvar_not_a_string:1:1-15 $ std.extVar(42) diff --git a/testdata/extvar_unknown.golden b/testdata/extvar_unknown.golden index 52141a0..671afa1 100644 --- a/testdata/extvar_unknown.golden +++ b/testdata/extvar_unknown.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Undefined external variable: UNKNOWN ------------------------------------------------- - testdata/extvar_unknown:1:1-22 builtin function + testdata/extvar_unknown:1:1-22 $ std.extVar("UNKNOWN") diff --git a/testdata/function_manifested.golden b/testdata/function_manifested.golden index ab80807..a8f6e21 100644 --- a/testdata/function_manifested.golden +++ b/testdata/function_manifested.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: couldn't manifest function in JSON output. +RUNTIME ERROR: couldn't manifest function as JSON ------------------------------------------------- During manifestation diff --git a/testdata/function_plus_string.golden b/testdata/function_plus_string.golden index eb6834d..9a8a00c 100644 --- a/testdata/function_plus_string.golden +++ b/testdata/function_plus_string.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: couldn't manifest function in JSON output. +RUNTIME ERROR: couldn't manifest function as JSON ------------------------------------------------- testdata/function_plus_string:1:1-24 $ diff --git a/testdata/function_too_many_params.golden b/testdata/function_too_many_params.golden index 273e011..4004c87 100644 --- a/testdata/function_too_many_params.golden +++ b/testdata/function_too_many_params.golden @@ -1,5 +1,5 @@ RUNTIME ERROR: Missing argument: x ------------------------------------------------- - Top-level function + Top-level function call diff --git a/testdata/native5.golden b/testdata/native5.golden index be6e574..e27561d 100644 --- a/testdata/native5.golden +++ b/testdata/native5.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: couldn't manifest function in JSON output. +RUNTIME ERROR: couldn't manifest function as JSON ------------------------------------------------- testdata/native5:1:1-42 $ diff --git a/testdata/object_comp_duplicate.golden b/testdata/object_comp_duplicate.golden index 4857142..a6b445e 100644 --- a/testdata/object_comp_duplicate.golden +++ b/testdata/object_comp_duplicate.golden @@ -1,6 +1,8 @@ RUNTIME ERROR: Duplicate field name: "x" ------------------------------------------------- - builtin function <$objectFlatMerge> + testdata/object_comp_duplicate:1:1-31 + +{ [x]: x for x in ["x", "x"] } ------------------------------------------------- During evaluation diff --git a/testdata/object_comp_err_index.golden b/testdata/object_comp_err_index.golden index e2e919b..65ffba3 100644 --- a/testdata/object_comp_err_index.golden +++ b/testdata/object_comp_err_index.golden @@ -5,7 +5,9 @@ RUNTIME ERROR: xxx { [error "xxx"]: 42 for x in [1] } ------------------------------------------------- - builtin function <$objectFlatMerge> + testdata/object_comp_err_index:1:1-35 + +{ [error "xxx"]: 42 for x in [1] } ------------------------------------------------- During evaluation diff --git a/testdata/object_comp_int_index.golden b/testdata/object_comp_int_index.golden index 5eb2ceb..4d0bcbd 100644 --- a/testdata/object_comp_int_index.golden +++ b/testdata/object_comp_int_index.golden @@ -5,7 +5,9 @@ RUNTIME ERROR: Field name must be string, got number { [x]: x for x in [1, 2, 3] } ------------------------------------------------- - builtin function <$objectFlatMerge> + testdata/object_comp_int_index:1:1-30 + +{ [x]: x for x in [1, 2, 3] } ------------------------------------------------- During evaluation diff --git a/testdata/percent_bad.golden b/testdata/percent_bad.golden index ff11b53..3b755b3 100644 --- a/testdata/percent_bad.golden +++ b/testdata/percent_bad.golden @@ -5,7 +5,9 @@ RUNTIME ERROR: Operator % cannot be used on types number and string. error 'Operator % cannot be used on types ' + std.type(a) + ' and ' + std.type(b) + '.', ------------------------------------------------- - + testdata/percent_bad:1:1-9 + +42 % "x" ------------------------------------------------- During evaluation diff --git a/testdata/percent_bad2.golden b/testdata/percent_bad2.golden index d4d6d8a..53d9438 100644 --- a/testdata/percent_bad2.golden +++ b/testdata/percent_bad2.golden @@ -20,7 +20,9 @@ RUNTIME ERROR: Too many values to format: 1, expected 0 std.format(a, b) ------------------------------------------------- - + testdata/percent_bad2:1:1-9 + +"x" % 42 ------------------------------------------------- During evaluation diff --git a/testdata/percent_bad3.golden b/testdata/percent_bad3.golden index 17c4083..7523447 100644 --- a/testdata/percent_bad3.golden +++ b/testdata/percent_bad3.golden @@ -5,7 +5,9 @@ RUNTIME ERROR: Operator % cannot be used on types function and number. error 'Operator % cannot be used on types ' + std.type(a) + ' and ' + std.type(b) + '.', ------------------------------------------------- - + testdata/percent_bad3:1:1-21 + +(function(x) x) % 42 ------------------------------------------------- During evaluation diff --git a/testdata/percent_format_str4.golden b/testdata/percent_format_str4.golden index 270572d..6d81a01 100644 --- a/testdata/percent_format_str4.golden +++ b/testdata/percent_format_str4.golden @@ -20,7 +20,9 @@ RUNTIME ERROR: Too many values to format: 2, expected 1 std.format(a, b) ------------------------------------------------- - + testdata/percent_format_str4:1:1-20 + +"x %s" % ["y", "z"] ------------------------------------------------- During evaluation diff --git a/testdata/percent_format_str5.golden b/testdata/percent_format_str5.golden index 6e912a2..3cb3961 100644 --- a/testdata/percent_format_str5.golden +++ b/testdata/percent_format_str5.golden @@ -37,7 +37,9 @@ RUNTIME ERROR: Not enough values to format: 1, expected more than 1 std.format(a, b) ------------------------------------------------- - + testdata/percent_format_str5:1:1-18 + +"x %s %s" % ["y"] ------------------------------------------------- During evaluation diff --git a/testdata/percent_format_str6.golden b/testdata/percent_format_str6.golden index cd41d86..b497978 100644 --- a/testdata/percent_format_str6.golden +++ b/testdata/percent_format_str6.golden @@ -37,7 +37,9 @@ RUNTIME ERROR: Not enough values to format: 1, expected more than 1 std.format(a, b) ------------------------------------------------- - + testdata/percent_format_str6:1:1-16 + +"x %s %s" % "y" ------------------------------------------------- During evaluation diff --git a/testdata/percent_format_str7.golden b/testdata/percent_format_str7.golden index 71f1a55..7446801 100644 --- a/testdata/percent_format_str7.golden +++ b/testdata/percent_format_str7.golden @@ -38,7 +38,9 @@ RUNTIME ERROR: Format required number at 0, got string std.format(a, b) ------------------------------------------------- - + testdata/percent_format_str7:1:1-15 + +"x %d" % ["y"] ------------------------------------------------- During evaluation diff --git a/testdata/percent_mod_int5.golden b/testdata/percent_mod_int5.golden index e21ec88..972ac7a 100644 --- a/testdata/percent_mod_int5.golden +++ b/testdata/percent_mod_int5.golden @@ -1,11 +1,13 @@ RUNTIME ERROR: Division by zero. ------------------------------------------------- - :235:7-23 builtin function + :235:7-23 function std.modulo(a, b) ------------------------------------------------- - + testdata/percent_mod_int5:1:1-7 + +42 % 0 ------------------------------------------------- During evaluation diff --git a/testdata/pow4.golden b/testdata/pow4.golden index 60a3e1d..cc04288 100644 --- a/testdata/pow4.golden +++ b/testdata/pow4.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Not a number ------------------------------------------------- - testdata/pow4:1:1-17 builtin function + testdata/pow4:1:1-17 $ std.pow(-1, 0.2) diff --git a/testdata/pow7.golden b/testdata/pow7.golden index 67a3133..ea83bf6 100644 --- a/testdata/pow7.golden +++ b/testdata/pow7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Overflow ------------------------------------------------- - testdata/pow7:2:1-23 builtin function + testdata/pow7:2:1-23 $ std.pow(1.1, 7447.082) diff --git a/testdata/pow8.golden b/testdata/pow8.golden index cdeb291..766801e 100644 --- a/testdata/pow8.golden +++ b/testdata/pow8.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/pow8:1:1-19 builtin function + testdata/pow8:1:1-19 $ std.pow("xxx", 42) diff --git a/testdata/pow9.golden b/testdata/pow9.golden index 0862b2c..412a4f6 100644 --- a/testdata/pow9.golden +++ b/testdata/pow9.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/pow9:1:1-19 builtin function + testdata/pow9:1:1-19 $ std.pow(42, "xxx") diff --git a/testdata/std.codepoint3.golden b/testdata/std.codepoint3.golden index 47a5ff7..94b0dff 100644 --- a/testdata/std.codepoint3.golden +++ b/testdata/std.codepoint3.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: codepoint takes a string of length 1, got length 2 ------------------------------------------------- - testdata/std.codepoint3:1:1-20 builtin function + testdata/std.codepoint3:1:1-20 $ std.codepoint("aa") diff --git a/testdata/std.codepoint6.golden b/testdata/std.codepoint6.golden index ffbf075..59cc994 100644 --- a/testdata/std.codepoint6.golden +++ b/testdata/std.codepoint6.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: codepoint takes a string of length 1, got length 0 ------------------------------------------------- - testdata/std.codepoint6:1:1-18 builtin function + testdata/std.codepoint6:1:1-18 $ std.codepoint("") diff --git a/testdata/std.codepoint7.golden b/testdata/std.codepoint7.golden index 5c255c4..8a8726c 100644 --- a/testdata/std.codepoint7.golden +++ b/testdata/std.codepoint7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: codepoint takes a string of length 1, got length 2 ------------------------------------------------- - testdata/std.codepoint7:2:1-21 builtin function + testdata/std.codepoint7:2:1-21 $ std.codepoint("ą") diff --git a/testdata/std.codepoint8.golden b/testdata/std.codepoint8.golden index cb8774d..95c5da5 100644 --- a/testdata/std.codepoint8.golden +++ b/testdata/std.codepoint8.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected string ------------------------------------------------- - testdata/std.codepoint8:1:1-18 builtin function + testdata/std.codepoint8:1:1-18 $ std.codepoint(42) diff --git a/testdata/std.filter4.golden b/testdata/std.filter4.golden index a401b44..e62c173 100644 --- a/testdata/std.filter4.golden +++ b/testdata/std.filter4.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected function ------------------------------------------------- - testdata/std.filter4:1:1-19 builtin function + testdata/std.filter4:1:1-19 $ std.filter(42, []) diff --git a/testdata/std.filter5.golden b/testdata/std.filter5.golden index 4fb6484..2362139 100644 --- a/testdata/std.filter5.golden +++ b/testdata/std.filter5.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected array ------------------------------------------------- - testdata/std.filter5:1:1-31 builtin function + testdata/std.filter5:1:1-31 $ std.filter(function(n) 42, 42) diff --git a/testdata/std.filter6.golden b/testdata/std.filter6.golden index ef8340c..8860cbc 100644 --- a/testdata/std.filter6.golden +++ b/testdata/std.filter6.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected array ------------------------------------------------- - testdata/std.filter6:1:1-21 builtin function + testdata/std.filter6:1:1-21 $ std.filter(42, "42") diff --git a/testdata/std.filter8.golden b/testdata/std.filter8.golden index 2dde037..6fa2af1 100644 --- a/testdata/std.filter8.golden +++ b/testdata/std.filter8.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type function, expected array ------------------------------------------------- - testdata/std.filter8:1:1-36 builtin function + testdata/std.filter8:1:1-36 $ std.filter([42], function(i) "xxx") diff --git a/testdata/std.filter_swapped_args.golden b/testdata/std.filter_swapped_args.golden index 77c61cd..3bd21d7 100644 --- a/testdata/std.filter_swapped_args.golden +++ b/testdata/std.filter_swapped_args.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type function, expected array ------------------------------------------------- - testdata/std.filter_swapped_args:1:1-38 builtin function + testdata/std.filter_swapped_args:1:1-38 $ std.filter([1,2,3], function(n) true) diff --git a/testdata/std.flatmap5.golden b/testdata/std.flatmap5.golden index a7d5754..7d76a36 100644 --- a/testdata/std.flatmap5.golden +++ b/testdata/std.flatmap5.golden @@ -5,7 +5,7 @@ RUNTIME ERROR: a local failWith(x) = error x; ------------------------------------------------- - testdata/std.flatmap5:2:10-48 builtin function + testdata/std.flatmap5:2:10-48 thunk from <$> std.type(std.flatMap(failWith, ["a", "b", "c"])) diff --git a/testdata/std.join7.golden b/testdata/std.join7.golden index 208dd58..0135a11 100644 --- a/testdata/std.join7.golden +++ b/testdata/std.join7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type array, expected string ------------------------------------------------- - testdata/std.join7:1:1-27 builtin function + testdata/std.join7:1:1-27 $ std.join("aa", [[1], [2]]) diff --git a/testdata/std.join8.golden b/testdata/std.join8.golden index a8c5d9e..7dfced7 100644 --- a/testdata/std.join8.golden +++ b/testdata/std.join8.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected array ------------------------------------------------- - testdata/std.join8:1:1-33 builtin function + testdata/std.join8:1:1-33 $ std.join([3, 4], [[1, 2], "56"]) diff --git a/testdata/std.makeArray_bad.golden b/testdata/std.makeArray_bad.golden index f322f0a..314100d 100644 --- a/testdata/std.makeArray_bad.golden +++ b/testdata/std.makeArray_bad.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/std.makeArray_bad:1:1-36 builtin function + testdata/std.makeArray_bad:1:1-36 $ std.makeArray("xxx", function(i) i) diff --git a/testdata/std.makeArray_bad2.golden b/testdata/std.makeArray_bad2.golden index 89e2632..3af45fb 100644 --- a/testdata/std.makeArray_bad2.golden +++ b/testdata/std.makeArray_bad2.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected function ------------------------------------------------- - testdata/std.makeArray_bad2:1:1-25 builtin function + testdata/std.makeArray_bad2:1:1-25 $ std.makeArray(42, "xxx") diff --git a/testdata/std.makeArray_noninteger.golden b/testdata/std.makeArray_noninteger.golden index 67e94ae..ca14062 100644 --- a/testdata/std.makeArray_noninteger.golden +++ b/testdata/std.makeArray_noninteger.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Expected an integer, but got 2.5 ------------------------------------------------- - testdata/std.makeArray_noninteger:1:1-34 builtin function + testdata/std.makeArray_noninteger:1:1-34 $ std.makeArray(2.5, function(i) i) diff --git a/testdata/std.makeArray_noninteger_big.golden b/testdata/std.makeArray_noninteger_big.golden index ec6ea50..29748da 100644 --- a/testdata/std.makeArray_noninteger_big.golden +++ b/testdata/std.makeArray_noninteger_big.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Expected an integer, but got 1e+100 ------------------------------------------------- - testdata/std.makeArray_noninteger_big:1:1-36 builtin function + testdata/std.makeArray_noninteger_big:1:1-36 $ std.makeArray(1e100, function(i) i) diff --git a/testdata/std.md5_6.golden b/testdata/std.md5_6.golden index 872254b..c904135 100644 --- a/testdata/std.md5_6.golden +++ b/testdata/std.md5_6.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected string ------------------------------------------------- - testdata/std.md5_6:1:1-12 builtin function + testdata/std.md5_6:1:1-12 $ std.md5(42) diff --git a/testdata/std.modulo2.golden b/testdata/std.modulo2.golden index 7324b2c..926c246 100644 --- a/testdata/std.modulo2.golden +++ b/testdata/std.modulo2.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/std.modulo2:1:1-22 builtin function + testdata/std.modulo2:1:1-22 $ std.modulo("xxx", 42) diff --git a/testdata/std.modulo3.golden b/testdata/std.modulo3.golden index 35caae3..33697f3 100644 --- a/testdata/std.modulo3.golden +++ b/testdata/std.modulo3.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type string, expected number ------------------------------------------------- - testdata/std.modulo3:1:1-22 builtin function + testdata/std.modulo3:1:1-22 $ std.modulo("xxx", 42) diff --git a/testdata/std.primitiveEquals13.golden b/testdata/std.primitiveEquals13.golden index bd00ceb..2aec549 100644 --- a/testdata/std.primitiveEquals13.golden +++ b/testdata/std.primitiveEquals13.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: primitiveEquals operates on primitive types, got array ------------------------------------------------- - testdata/std.primitiveEquals13:1:1-28 builtin function + testdata/std.primitiveEquals13:1:1-28 $ std.primitiveEquals([], []) diff --git a/testdata/std.primitiveEquals6.golden b/testdata/std.primitiveEquals6.golden index 94fdaa6..c21b732 100644 --- a/testdata/std.primitiveEquals6.golden +++ b/testdata/std.primitiveEquals6.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: primitiveEquals operates on primitive types, got object ------------------------------------------------- - testdata/std.primitiveEquals6:1:1-28 builtin function + testdata/std.primitiveEquals6:1:1-28 $ std.primitiveEquals({}, {}) diff --git a/testdata/std.primitiveEquals7.golden b/testdata/std.primitiveEquals7.golden index 8871ec0..b1e81b4 100644 --- a/testdata/std.primitiveEquals7.golden +++ b/testdata/std.primitiveEquals7.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Cannot test equality of functions ------------------------------------------------- - testdata/std.primitiveEquals7:1:1-50 builtin function + testdata/std.primitiveEquals7:1:1-50 $ std.primitiveEquals(function() 42, function() 42) diff --git a/testdata/std.sort3.golden b/testdata/std.sort3.golden index 3e2ce41..f5fb6b7 100644 --- a/testdata/std.sort3.golden +++ b/testdata/std.sort3.golden @@ -5,7 +5,7 @@ RUNTIME ERROR: foo std.sort([1,2, error "foo"]) ------------------------------------------------- - testdata/std.sort3:1:1-29 builtin function + testdata/std.sort3:1:1-29 $ std.sort([1,2, error "foo"]) diff --git a/testdata/std.sort4.golden b/testdata/std.sort4.golden index 1c82e67..70c4fc3 100644 --- a/testdata/std.sort4.golden +++ b/testdata/std.sort4.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: Unexpected type number, expected array ------------------------------------------------- - testdata/std.sort4:1:1-29 builtin function + testdata/std.sort4:1:1-29 $ std.sort([1, [error "foo"]]) diff --git a/testdata/strReplace3.golden b/testdata/strReplace3.golden index 082d9c2..8c866b0 100644 --- a/testdata/strReplace3.golden +++ b/testdata/strReplace3.golden @@ -1,6 +1,6 @@ RUNTIME ERROR: 'from' string must not be zero length. ------------------------------------------------- - testdata/strReplace3:1:1-35 builtin function + testdata/strReplace3:1:1-35 $ std.strReplace("test", "", "blah") diff --git a/testdata/string_plus_function.golden b/testdata/string_plus_function.golden index e28f2b5..4cf8dbd 100644 --- a/testdata/string_plus_function.golden +++ b/testdata/string_plus_function.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: couldn't manifest function in JSON output. +RUNTIME ERROR: couldn't manifest function as JSON ------------------------------------------------- testdata/string_plus_function:1:1-24 $ diff --git a/tests.sh b/tests.sh index 1dfae5e..a281864 100755 --- a/tests.sh +++ b/tests.sh @@ -3,6 +3,7 @@ set -e PYTHON_COMMAND=${PYTHON_COMMAND:=python} +JSONNET_CPP_DIR=${JSONNET_CPP_DIR:=$PWD/cpp-jsonnet} set -x @@ -19,6 +20,7 @@ else fi export IMPLEMENTATION=golang +export OVERRIDE_DIR="$PWD/testdata/cpp-tests-override/" go build ./cmd/jsonnet go build ./cmd/jsonnetfmt @@ -28,5 +30,5 @@ export DISABLE_ERROR_TESTS=true export JSONNETFMT_BIN="$PWD/jsonnetfmt" export JSONNET_BIN="$PWD/jsonnet" -cd cpp-jsonnet +cd "$JSONNET_CPP_DIR" exec ./tests.sh diff --git a/thunks.go b/thunks.go index cb21769..1cd4175 100644 --- a/thunks.go +++ b/thunks.go @@ -32,7 +32,7 @@ type readyValue struct { content value } -func (rv *readyValue) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) { +func (rv *readyValue) evaluate(i *interpreter, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) { return rv.content, nil } @@ -58,14 +58,14 @@ func readyThunk(content value) *cachedThunk { return &cachedThunk{content: content} } -func (t *cachedThunk) getValue(i *interpreter, trace traceElement) (value, error) { +func (t *cachedThunk) getValue(i *interpreter) (value, error) { if t.content != nil { return t.content, nil } if t.err != nil { return nil, t.err } - v, err := i.EvalInCleanEnv(trace, t.env, t.body, false) + v, err := i.EvalInCleanEnv(t.env, t.body, false) if err != nil { // TODO(sbarzowski) perhaps cache errors as well // may be necessary if we allow handling them in any way @@ -87,9 +87,9 @@ type codeUnboundField struct { body ast.Node } -func (f *codeUnboundField) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) { +func (f *codeUnboundField) evaluate(i *interpreter, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) { env := makeEnvironment(origBindings, sb) - return i.EvalInCleanEnv(trace, &env, f.body, false) + return i.EvalInCleanEnv(&env, f.body, false) } // Provide additional bindings for a field. It shadows bindings from the object. @@ -99,7 +99,7 @@ type bindingsUnboundField struct { bindings bindingFrame } -func (f *bindingsUnboundField) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) { +func (f *bindingsUnboundField) evaluate(i *interpreter, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) { upValues := make(bindingFrame) for variable, pvalue := range origBindings { upValues[variable] = pvalue @@ -107,7 +107,7 @@ func (f *bindingsUnboundField) evaluate(i *interpreter, trace traceElement, sb s for variable, pvalue := range f.bindings { upValues[variable] = pvalue } - return f.inner.evaluate(i, trace, sb, upValues, fieldName) + return f.inner.evaluate(i, sb, upValues, fieldName) } // plusSuperUnboundField represents a `field+: ...` that hasn't been bound to an object. @@ -115,19 +115,19 @@ type plusSuperUnboundField struct { inner unboundField } -func (f *plusSuperUnboundField) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) { - right, err := f.inner.evaluate(i, trace, sb, origBinding, fieldName) +func (f *plusSuperUnboundField) evaluate(i *interpreter, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) { + right, err := f.inner.evaluate(i, sb, origBinding, fieldName) if err != nil { return nil, err } if !objectHasField(sb.super(), fieldName, withHidden) { return right, nil } - left, err := objectIndex(i, trace, sb.super(), fieldName) + left, err := objectIndex(i, sb.super(), fieldName) if err != nil { return nil, err } - return builtinPlus(i, trace, left, right) + return builtinPlus(i, left, right) } // evalCallables @@ -141,9 +141,9 @@ type closure struct { params []namedParameter } -func forceThunks(i *interpreter, trace traceElement, args *bindingFrame) error { +func forceThunks(i *interpreter, args *bindingFrame) error { for _, arg := range *args { - _, err := arg.getValue(i, trace) + _, err := arg.getValue(i) if err != nil { return err } @@ -151,7 +151,7 @@ func forceThunks(i *interpreter, trace traceElement, args *bindingFrame) error { return nil } -func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) { +func (closure *closure) evalCall(arguments callArguments, i *interpreter) (value, error) { argThunks := make(bindingFrame) parameters := closure.parameters() for i, arg := range arguments.positional { @@ -175,7 +175,7 @@ func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace } if arguments.tailstrict { - err := forceThunks(i, trace, &argThunks) + err := forceThunks(i, &argThunks) if err != nil { return nil, err } @@ -185,7 +185,7 @@ func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace addBindings(closure.env.upValues, argThunks), closure.env.selfBinding, ) - return i.EvalInCleanEnv(trace, &calledEnvironment, closure.function.Body, arguments.tailstrict) + return i.EvalInCleanEnv(&calledEnvironment, closure.function.Body, arguments.tailstrict) } func (closure *closure) parameters() []namedParameter { @@ -220,15 +220,15 @@ 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) { +func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter) (value, error) { flatArgs := flattenArgs(arguments, native.parameters(), []value{}) nativeArgs := make([]interface{}, 0, len(flatArgs)) for _, arg := range flatArgs { - v, err := i.evaluatePV(arg, trace) + v, err := i.evaluatePV(arg) if err != nil { return nil, err } - json, err := i.manifestJSON(trace, v) + json, err := i.manifestJSON(v) if err != nil { return nil, err } @@ -236,9 +236,9 @@ func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter, } resultJSON, err := native.Func(nativeArgs) if err != nil { - return nil, i.Error(err.Error(), trace) + return nil, i.Error(err.Error()) } - return jsonToValue(i, trace, resultJSON) + return jsonToValue(i, resultJSON) } // Parameters returns a NativeFunction's parameters. diff --git a/value.go b/value.go index 5e05640..7598a7d 100644 --- a/value.go +++ b/value.go @@ -58,7 +58,7 @@ var arrayType = &valueType{"array"} // TODO(sbarzowski) perhaps call it just "Thunk"? type potentialValue interface { // fromWhere keeps the information from where the evaluation was requested. - getValue(i *interpreter, fromWhere traceElement) (value, error) + getValue(i *interpreter) (value, error) aPotentialValue() } @@ -78,7 +78,7 @@ type valueString interface { length() int getRunes() []rune getGoString() string - index(i *interpreter, trace traceElement, index int) (value, error) + index(i *interpreter, index int) (value, error) } // valueFlatString represents a string value, internally using a []rune for quick @@ -89,11 +89,11 @@ type valueFlatString struct { value []rune } -func (s *valueFlatString) index(i *interpreter, trace traceElement, index int) (value, error) { +func (s *valueFlatString) index(i *interpreter, index int) (value, error) { if 0 <= index && index < s.length() { return makeValueString(string(s.value[index])), nil } - return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, s.length()), trace) + return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, s.length())) } func (s *valueFlatString) getRunes() []rune { @@ -142,12 +142,12 @@ func (s *valueStringTree) flattenToLeft() { } } -func (s *valueStringTree) index(i *interpreter, trace traceElement, index int) (value, error) { +func (s *valueStringTree) index(i *interpreter, index int) (value, error) { if 0 <= index && index < s.len { s.flattenToLeft() - return s.left.index(i, trace, index) + return s.left.index(i, index) } - return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, s.length()), trace) + return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, s.length())) } func (s *valueStringTree) getRunes() []rune { @@ -290,11 +290,11 @@ type valueArray struct { elements []*cachedThunk } -func (arr *valueArray) index(i *interpreter, trace traceElement, index int) (value, error) { +func (arr *valueArray) index(i *interpreter, index int) (value, error) { if 0 <= index && index < arr.length() { - return i.evaluatePV(arr.elements[index], trace) + return i.evaluatePV(arr.elements[index]) } - return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, arr.length()), trace) + return nil, i.Error(fmt.Sprintf("Index %d out of bounds, not within [0, %v)", index, arr.length())) } func (arr *valueArray) length() int { @@ -337,29 +337,29 @@ type valueFunction struct { // TODO(sbarzowski) better name? type evalCallable interface { - evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) + evalCall(args callArguments, i *interpreter) (value, error) parameters() []namedParameter } -func (f *valueFunction) call(i *interpreter, trace traceElement, args callArguments) (value, error) { - err := checkArguments(i, trace, args, f.parameters()) +func (f *valueFunction) call(i *interpreter, args callArguments) (value, error) { + err := checkArguments(i, args, f.parameters()) if err != nil { return nil, err } - return f.ec.evalCall(args, i, trace) + return f.ec.evalCall(args, i) } func (f *valueFunction) parameters() []namedParameter { return f.ec.parameters() } -func checkArguments(i *interpreter, trace traceElement, args callArguments, params []namedParameter) error { +func checkArguments(i *interpreter, args callArguments, params []namedParameter) error { numPassed := len(args.positional) maxExpected := len(params) if numPassed > maxExpected { - return i.Error(fmt.Sprintf("function expected %v positional argument(s), but got %v", maxExpected, numPassed), trace) + return i.Error(fmt.Sprintf("function expected %v positional argument(s), but got %v", maxExpected, numPassed)) } // Parameter names the function will accept. @@ -375,17 +375,17 @@ func checkArguments(i *interpreter, trace traceElement, args callArguments, para } for _, arg := range args.named { if _, present := received[arg.name]; present { - return i.Error(fmt.Sprintf("Argument %v already provided", arg.name), trace) + return i.Error(fmt.Sprintf("Argument %v already provided", arg.name)) } if _, present := accepted[arg.name]; !present { - return i.Error(fmt.Sprintf("function has no parameter %v", arg.name), trace) + return i.Error(fmt.Sprintf("function has no parameter %v", arg.name)) } received[arg.name] = true } for _, param := range params { if _, present := received[param.name]; !present && param.defaultArg == nil { - return i.Error(fmt.Sprintf("Missing argument: %v", param.name), trace) + return i.Error(fmt.Sprintf("Missing argument: %v", param.name)) } } @@ -492,8 +492,8 @@ func (*valueObject) getType() *valueType { return objectType } -func (obj *valueObject) index(i *interpreter, trace traceElement, field string) (value, error) { - return objectIndex(i, trace, objectBinding(obj), field) +func (obj *valueObject) index(i *interpreter, field string) (value, error) { + return objectIndex(i, objectBinding(obj), field) } func (obj *valueObject) assertionsChecked() bool { @@ -545,14 +545,14 @@ type simpleObject struct { locals []objectLocal } -func checkAssertionsHelper(i *interpreter, trace traceElement, obj *valueObject, curr uncachedObject, superDepth int) error { +func checkAssertionsHelper(i *interpreter, obj *valueObject, curr uncachedObject, superDepth int) error { switch curr := curr.(type) { case *extendedObject: - err := checkAssertionsHelper(i, trace, obj, curr.right, superDepth) + err := checkAssertionsHelper(i, obj, curr.right, superDepth) if err != nil { return err } - err = checkAssertionsHelper(i, trace, obj, curr.left, superDepth+curr.right.inheritanceSize()) + err = checkAssertionsHelper(i, obj, curr.left, superDepth+curr.right.inheritanceSize()) if err != nil { return err } @@ -561,7 +561,7 @@ func checkAssertionsHelper(i *interpreter, trace traceElement, obj *valueObject, for _, assert := range curr.asserts { sb := selfBinding{self: obj, superDepth: superDepth} fieldUpValues := prepareFieldUpvalues(sb, curr.upValues, curr.locals) - _, err := assert.evaluate(i, trace, sb, fieldUpValues, "") + _, err := assert.evaluate(i, sb, fieldUpValues, "") if err != nil { return err } @@ -574,13 +574,13 @@ func checkAssertionsHelper(i *interpreter, trace traceElement, obj *valueObject, } } -func checkAssertions(i *interpreter, trace traceElement, obj *valueObject) error { +func checkAssertions(i *interpreter, obj *valueObject) error { if !obj.assertionsChecked() { // Assertions may refer to the object that will normally // trigger checking of assertions, resulting in an endless recursion. // To avoid that, while we check them, we treat them as already passed. obj.setAssertionsCheckResult(errNoErrorInObjectInvariants) - obj.setAssertionsCheckResult(checkAssertionsHelper(i, trace, obj, obj.uncached, 0)) + obj.setAssertionsCheckResult(checkAssertionsHelper(i, obj, obj.uncached, 0)) } return obj.getAssertionsCheckResult() } @@ -610,7 +610,7 @@ type simpleObjectField struct { // unboundField is a field that doesn't know yet in which object it is. type unboundField interface { - evaluate(i *interpreter, trace traceElement, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) + evaluate(i *interpreter, sb selfBinding, origBinding bindingFrame, fieldName string) (value, error) } // extendedObject represents an object created through inheritance (left + right). @@ -699,18 +699,18 @@ func prepareFieldUpvalues(sb selfBinding, upValues bindingFrame, locals []object return newUpValues } -func objectIndex(i *interpreter, trace traceElement, sb selfBinding, fieldName string) (value, error) { - err := checkAssertions(i, trace, sb.self) +func objectIndex(i *interpreter, sb selfBinding, fieldName string) (value, error) { + err := checkAssertions(i, sb.self) if err != nil { return nil, err } if sb.superDepth >= sb.self.uncached.inheritanceSize() { - return nil, i.Error("Attempt to use super when there is no super class.", trace) + return nil, i.Error("Attempt to use super when there is no super class.") } found, field, upValues, locals, foundAt := findField(sb.self.uncached, sb.superDepth, fieldName) if !found { - return nil, i.Error(fmt.Sprintf("Field does not exist: %s", fieldName), trace) + return nil, i.Error(fmt.Sprintf("Field does not exist: %s", fieldName)) } if val, ok := sb.self.cache[objectCacheKey{field: fieldName, depth: foundAt}]; ok { @@ -720,7 +720,7 @@ func objectIndex(i *interpreter, trace traceElement, sb selfBinding, fieldName s fieldSelfBinding := selfBinding{self: sb.self, superDepth: foundAt} fieldUpValues := prepareFieldUpvalues(fieldSelfBinding, upValues, locals) - val, err := field.field.evaluate(i, trace, fieldSelfBinding, fieldUpValues, fieldName) + val, err := field.field.evaluate(i, fieldSelfBinding, fieldUpValues, fieldName) if err == nil { sb.self.cache[objectCacheKey{field: fieldName, depth: foundAt}] = val