mirror of
https://github.com/google/go-jsonnet.git
synced 2025-08-08 07:17:12 +02:00
Fix up lint errors.
Also: * Made all types used in errors public. * Made interpreter receiver a pointer. This will reduce GC load for deep stacks.
This commit is contained in:
parent
bf2c1df9e5
commit
0eedf437b1
@ -31,8 +31,9 @@ type vmExt struct {
|
|||||||
|
|
||||||
type vmExtMap map[string]vmExt
|
type vmExtMap map[string]vmExt
|
||||||
|
|
||||||
|
// RuntimeError is an error discovered during evaluation of the program
|
||||||
type RuntimeError struct {
|
type RuntimeError struct {
|
||||||
StackTrace []traceFrame
|
StackTrace []TraceFrame
|
||||||
Msg string
|
Msg string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +128,8 @@ func makeValueArray(elements []thunk) *valueArray {
|
|||||||
|
|
||||||
// The stack
|
// The stack
|
||||||
|
|
||||||
type traceFrame struct {
|
// TraceFrame is a single frame of the call stack.
|
||||||
|
type TraceFrame struct {
|
||||||
Loc LocationRange
|
Loc LocationRange
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
@ -158,17 +160,17 @@ type interpreter struct {
|
|||||||
ExternalVars vmExtMap
|
ExternalVars vmExtMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this interpreter) execute(ast_ astNode) (value, error) {
|
func (i *interpreter) execute(a astNode) (value, error) {
|
||||||
// TODO(dcunnin): All the other cases...
|
// TODO(dcunnin): All the other cases...
|
||||||
switch ast := ast_.(type) {
|
switch ast := a.(type) {
|
||||||
case *astBinary:
|
case *astBinary:
|
||||||
// TODO(dcunnin): Assume it's + on numbers for now
|
// TODO(dcunnin): Assume it's + on numbers for now
|
||||||
leftVal, err := this.execute(ast.left)
|
leftVal, err := i.execute(ast.left)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
leftNum := leftVal.(*valueNumber).value
|
leftNum := leftVal.(*valueNumber).value
|
||||||
rightVal, err := this.execute(ast.right)
|
rightVal, err := i.execute(ast.right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -188,18 +190,17 @@ func (this interpreter) execute(ast_ astNode) (value, error) {
|
|||||||
func unparseNumber(v float64) string {
|
func unparseNumber(v float64) string {
|
||||||
if v == math.Floor(v) {
|
if v == math.Floor(v) {
|
||||||
return fmt.Sprintf("%.0f", 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(
|
func (i *interpreter) manifestJSON(v value, multiline bool, indent string, buf *bytes.Buffer) error {
|
||||||
v_ value, multiline bool, indent string, buf *bytes.Buffer) error {
|
|
||||||
// TODO(dcunnin): All the other types...
|
// TODO(dcunnin): All the other types...
|
||||||
switch v := v_.(type) {
|
switch v := v.(type) {
|
||||||
case *valueBoolean:
|
case *valueBoolean:
|
||||||
if v.value {
|
if v.value {
|
||||||
buf.WriteString("true")
|
buf.WriteString("true")
|
||||||
@ -217,16 +218,16 @@ func (this interpreter) manifestJson(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func execute(ast astNode, ext vmExtMap, maxStack int) (string, error) {
|
func execute(ast astNode, ext vmExtMap, maxStack int) (string, error) {
|
||||||
theInterpreter := interpreter{
|
i := interpreter{
|
||||||
Stack: makeCallStack(maxStack),
|
Stack: makeCallStack(maxStack),
|
||||||
ExternalVars: ext,
|
ExternalVars: ext,
|
||||||
}
|
}
|
||||||
result, err := theInterpreter.execute(ast)
|
result, err := i.execute(ast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
err = theInterpreter.manifestJson(result, true, "", &buffer)
|
err = i.manifestJSON(result, true, "", &buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
35
main.go
35
main.go
@ -16,29 +16,40 @@ limitations under the License.
|
|||||||
|
|
||||||
package jsonnet
|
package jsonnet
|
||||||
|
|
||||||
// Note: There are no garbage collection params because we're using the native Go garbage collector.
|
// Note: There are no garbage collection params because we're using the native
|
||||||
type Vm struct {
|
// Go garbage collector.
|
||||||
maxStack int
|
|
||||||
maxTrace int
|
// 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
|
ext vmExtMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeVm() *Vm {
|
// MakeVM creates a new VM with default parameters.
|
||||||
return &Vm{
|
func MakeVM() *VM {
|
||||||
maxStack: 500,
|
return &VM{
|
||||||
maxTrace: 20,
|
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}
|
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}
|
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)
|
tokens, err := lex(filename, snippet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -48,7 +59,7 @@ func (vm *Vm) EvaluateSnippet(filename string, snippet string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
ast, err = desugarFile(ast)
|
ast, err = desugarFile(ast)
|
||||||
output, err := execute(ast, vm.ext, vm.maxStack)
|
output, err := execute(ast, vm.ext, vm.MaxStack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ var mainTests = []mainTest{
|
|||||||
|
|
||||||
func TestMain(t *testing.T) {
|
func TestMain(t *testing.T) {
|
||||||
for _, test := range mainTests {
|
for _, test := range mainTests {
|
||||||
vm := MakeVm()
|
vm := MakeVM()
|
||||||
output, err := vm.EvaluateSnippet(test.name, test.input)
|
output, err := vm.EvaluateSnippet(test.name, test.input)
|
||||||
var errString string
|
var errString string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user