diff --git a/ast/ast.go b/ast/ast.go index 89ed5b3..7231a79 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -468,8 +468,6 @@ type ObjectField struct { Expr2, Expr3 Node // In scope of the object (can see self). } -// TODO(jbeda): Add the remaining constructor helpers here - func ObjectFieldLocalNoMethod(id *Identifier, body Node) ObjectField { return ObjectField{ObjectLocal, ObjectFieldVisible, false, false, nil, nil, id, nil, false, body, nil} } diff --git a/error_formatter.go b/error_formatter.go index 5259cf1..102b46e 100644 --- a/error_formatter.go +++ b/error_formatter.go @@ -25,7 +25,6 @@ import ( ) type ErrorFormatter struct { - // TODO(sbarzowski) use this // MaxStackTraceSize is the maximum length of stack trace before cropping MaxStackTraceSize int diff --git a/testdata/insuper2.golden b/testdata/insuper2.golden index e136bd4..22cb291 100644 --- a/testdata/insuper2.golden +++ b/testdata/insuper2.golden @@ -1,5 +1,3 @@ -testdata/insuper2:1:11-13 Expected token OPERATOR but got (in, "in") - -{ } { "x" in super } - - +{ + "x": false +} diff --git a/testdata/insuper2.jsonnet b/testdata/insuper2.jsonnet index 14b5581..bdc15b8 100644 --- a/testdata/insuper2.jsonnet +++ b/testdata/insuper2.jsonnet @@ -1 +1 @@ -{ } { "x" in super } +{ } { x: "x" in super } diff --git a/testdata/missing_super.golden b/testdata/missing_super.golden new file mode 100644 index 0000000..376aa86 --- /dev/null +++ b/testdata/missing_super.golden @@ -0,0 +1,10 @@ +RUNTIME ERROR: Attempt to use super when there is no super class. +------------------------------------------------- + testdata/missing_super:1:6-11 object + +{ x: super.x } + +------------------------------------------------- + During manifestation + + diff --git a/testdata/missing_super.jsonnet b/testdata/missing_super.jsonnet new file mode 100644 index 0000000..f46bc40 --- /dev/null +++ b/testdata/missing_super.jsonnet @@ -0,0 +1 @@ +{ x: super.x } diff --git a/testdata/object_invariant7.golden b/testdata/object_invariant7.golden index 98cc73a..fed3aa0 100644 --- a/testdata/object_invariant7.golden +++ b/testdata/object_invariant7.golden @@ -1,4 +1,4 @@ -RUNTIME ERROR: Field does not exist: x +RUNTIME ERROR: Attempt to use super when there is no super class. ------------------------------------------------- testdata/object_invariant7:1:16-21 object diff --git a/thunks.go b/thunks.go index 3f9d86f..778eedd 100644 --- a/thunks.go +++ b/thunks.go @@ -100,8 +100,6 @@ func (th *callThunk) getValue(i *interpreter, trace *TraceElement) (value, error // the first evaluation. // Note: All potentialValues are required to provide the same value every time, // so it's only there for efficiency. -// TODO(sbarzowski) better name? -// TODO(sbarzowski) force use cached/ready everywhere? perhaps an interface tag? // TODO(sbarzowski) investigate efficiency of various representations type cachedThunk struct { pv evaluable diff --git a/value.go b/value.go index b4c8232..4b62e8a 100644 --- a/value.go +++ b/value.go @@ -166,13 +166,14 @@ func int64ToValue(i int64) *valueNumber { return makeValueNumber(float64(i)) } -// TODO(dcunnin): Maybe intern values null, true, and false? type valueNull struct { valueBase } +var nullValue valueNull + func makeValueNull() *valueNull { - return &valueNull{} + return &nullValue } func (*valueNull) typename() string { @@ -274,9 +275,8 @@ func args(xs ...potentialValue) callArguments { // Object is a value that allows indexing (taking a value of a field) // and combining through mixin inheritence (operator +). // -// Accessing a field multiple times results in multiple evaluations. -// TODO(sbarzowski) This can be very easily avoided and currently innocent looking -// code may be in fact exponential. +// Note that every time a field is indexed it evaluates it again, there is +// no caching of field values. See: https://github.com/google/go-jsonnet/issues/113 type valueObject interface { value inheritanceSize() int @@ -471,7 +471,6 @@ type unboundField interface { // This represenation allows us to implement "+" in O(1), // but requires going through the tree and trying subsequent leafs for field access. // -// TODO(sbarzowski) consider other representations (this representation was chosen to stay close to C++ version) type valueExtendedObject struct { valueObjectBase left, right valueObject @@ -515,7 +514,6 @@ func findField(curr value, minSuperDepth int, f string) (*valueSimpleObjectField return &field, curr.upValues, 0 } } - // TODO(sbarzowski) add handling of "Attempt to use super when there is no super class." return nil, nil, 0 default: panic(fmt.Sprintf("Unknown object type %#v", curr)) @@ -527,6 +525,9 @@ func objectIndex(e *evaluator, sb selfBinding, fieldName string) (value, error) if err != nil { return nil, err } + if sb.superDepth >= sb.self.inheritanceSize() { + return nil, e.Error("Attempt to use super when there is no super class.") + } objp := tryObjectIndex(sb, fieldName, withHidden) if objp == nil { return nil, e.Error(fmt.Sprintf("Field does not exist: %s", fieldName)) diff --git a/vm.go b/vm.go index c1f0f71..c37cbb7 100644 --- a/vm.go +++ b/vm.go @@ -28,8 +28,6 @@ import ( // Note: There are no garbage collection params because we're using the native // Go garbage collector. -// TODO(sbarzowski) prepare API that maps 1-1 to libjsonnet api - // VM is the core interpreter and is the touchpoint used to parse and execute // Jsonnet. type VM struct { @@ -40,7 +38,6 @@ type VM struct { ef ErrorFormatter } -// TODO(sbarzowski) actually support these // External variable (or code) provided before execution type vmExt struct { value string // what is it?