diff --git a/interpreter.go b/interpreter.go index 847a72f..55454a2 100644 --- a/interpreter.go +++ b/interpreter.go @@ -31,8 +31,9 @@ type vmExt struct { type vmExtMap map[string]vmExt +// RuntimeError is an error discovered during evaluation of the program type RuntimeError struct { - StackTrace []traceFrame + StackTrace []TraceFrame Msg string } @@ -127,7 +128,8 @@ func makeValueArray(elements []thunk) *valueArray { // The stack -type traceFrame struct { +// TraceFrame is a single frame of the call stack. +type TraceFrame struct { Loc LocationRange Name string } @@ -158,17 +160,17 @@ type interpreter struct { ExternalVars vmExtMap } -func (this interpreter) execute(ast_ astNode) (value, error) { +func (i *interpreter) execute(a astNode) (value, error) { // TODO(dcunnin): All the other cases... - switch ast := ast_.(type) { + switch ast := a.(type) { case *astBinary: // TODO(dcunnin): Assume it's + on numbers for now - leftVal, err := this.execute(ast.left) + leftVal, err := i.execute(ast.left) if err != nil { return nil, err } leftNum := leftVal.(*valueNumber).value - rightVal, err := this.execute(ast.right) + rightVal, err := i.execute(ast.right) if err != nil { return nil, err } @@ -188,18 +190,17 @@ func (this interpreter) execute(ast_ astNode) (value, error) { func unparseNumber(v float64) string { if v == math.Floor(v) { return fmt.Sprintf("%.0f", v) - } else { - // See "What Every Computer Scientist Should Know About Floating-Point Arithmetic" - // Theorem 15 - // http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - return fmt.Sprintf("%.17g", v) } + + // See "What Every Computer Scientist Should Know About Floating-Point Arithmetic" + // Theorem 15 + // http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html + return fmt.Sprintf("%.17g", v) } -func (this interpreter) manifestJson( - v_ value, multiline bool, indent string, buf *bytes.Buffer) error { +func (i *interpreter) manifestJSON(v value, multiline bool, indent string, buf *bytes.Buffer) error { // TODO(dcunnin): All the other types... - switch v := v_.(type) { + switch v := v.(type) { case *valueBoolean: if v.value { buf.WriteString("true") @@ -217,16 +218,16 @@ func (this interpreter) manifestJson( } func execute(ast astNode, ext vmExtMap, maxStack int) (string, error) { - theInterpreter := interpreter{ + i := interpreter{ Stack: makeCallStack(maxStack), ExternalVars: ext, } - result, err := theInterpreter.execute(ast) + result, err := i.execute(ast) if err != nil { return "", err } var buffer bytes.Buffer - err = theInterpreter.manifestJson(result, true, "", &buffer) + err = i.manifestJSON(result, true, "", &buffer) if err != nil { return "", err } diff --git a/main.go b/main.go index 443f65c..fe72bf3 100644 --- a/main.go +++ b/main.go @@ -16,29 +16,40 @@ limitations under the License. package jsonnet -// Note: There are no garbage collection params because we're using the native Go garbage collector. -type Vm struct { - maxStack int - maxTrace int +// Note: There are no garbage collection params because we're using the native +// Go garbage collector. + +// VM is the core interpreter and is the touchpoint used to parse and execute +// Jsonnet. +type VM struct { + MaxStack int + MaxTrace int // The number of lines of stack trace to display (0 for all of them). ext vmExtMap } -func MakeVm() *Vm { - return &Vm{ - maxStack: 500, - maxTrace: 20, +// MakeVM creates a new VM with default parameters. +func MakeVM() *VM { + return &VM{ + MaxStack: 500, + MaxTrace: 20, } } -func (vm *Vm) ExtVar(key string, val string) { +// ExtVar binds a Jsonnet external var to the given value. +func (vm *VM) ExtVar(key string, val string) { vm.ext[key] = vmExt{value: val, isCode: false} } -func (vm *Vm) ExtCode(key string, val string) { +// ExtCode binds a Jsonnet external code var to the given value. +func (vm *VM) ExtCode(key string, val string) { vm.ext[key] = vmExt{value: val, isCode: true} } -func (vm *Vm) EvaluateSnippet(filename string, snippet string) (string, error) { +// EvaluateSnippet evaluates a string containing Jsonnet code, return a JSON +// string. +// +// The filename parameter is only used for error messages. +func (vm *VM) EvaluateSnippet(filename string, snippet string) (string, error) { tokens, err := lex(filename, snippet) if err != nil { return "", err @@ -48,7 +59,7 @@ func (vm *Vm) EvaluateSnippet(filename string, snippet string) (string, error) { return "", err } ast, err = desugarFile(ast) - output, err := execute(ast, vm.ext, vm.maxStack) + output, err := execute(ast, vm.ext, vm.MaxStack) if err != nil { return "", err } diff --git a/main_test.go b/main_test.go index 6f5f7dc..781dc98 100644 --- a/main_test.go +++ b/main_test.go @@ -40,7 +40,7 @@ var mainTests = []mainTest{ func TestMain(t *testing.T) { for _, test := range mainTests { - vm := MakeVm() + vm := MakeVM() output, err := vm.EvaluateSnippet(test.name, test.input) var errString string if err != nil {