func interpretDoubleQuotedStringInContext( vm *vm, stringValue ast.InterpolatedString, context Value, ) (Value, error) { str := stringValue.Value currentBytes := []byte{} bytesToInterpret := [][]byte{} insideInterpolation := false for i := 0; i < len(str); i++ { if insideInterpolation { currentBytes = append(currentBytes, str[i]) } if str[i] == '}' && i > 0 && str[i-1] != '\\' { insideInterpolation = false bytesToInterpret = append(bytesToInterpret, currentBytes) currentBytes = []byte{} } else if str[i] == '#' && len(str) > i && str[i+1] == '{' { insideInterpolation = true } } for _, bytes := range bytesToInterpret { substringToReplace := string(bytes) rubyValue, err := vm.EvaluateStringInContext(substringToReplace[1:len(substringToReplace)-1], context) if err != nil { return nil, err } valueAsString := gomads.Maybe(func() interface{} { method := rubyValue.Method("to_s") if method == nil { return nil } result, err := method.Execute(rubyValue, nil) if err != nil { return nil } return result.(*StringValue).RawString() }).OrSome(rubyValue.String()).Value().(string) str = strings.Replace(str, "#"+substringToReplace, valueAsString, 1) } return NewString(str, vm), nil }
func interpretConstantInContext( vm *vm, constantNode ast.Constant, context Value, ) (Value, error) { maybeTarget := gomads.Maybe(func() interface{} { if vm.currentModuleName == "" { return vm.CurrentClasses["Object"] } else { return nil } }).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentClasses[vm.currentModuleName] })).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentModules[vm.currentModuleName] })) target, ok := maybeTarget.Value().(Module) maybeConstant := gomads.Maybe(func() interface{} { constant, err := target.Constant(constantNode.Name) if err == nil { return constant } else { return nil } }).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentClasses[constantNode.Name] })).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentModules[constantNode.Name] })).OrSome(gomads.Maybe(func() interface{} { if vm.currentModuleName == "" { return nil } parts := strings.Split(vm.currentModuleName, "::") count := len(parts) - 1 for index, _ := range parts { namespace := append(parts[0:(count-index)], constantNode.Name) nameToLookup := strings.Join(namespace, "::") maybe := gomads.Maybe(func() interface{} { return vm.CurrentClasses[nameToLookup] }).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentModules[nameToLookup] })) something, ok := maybe.Value().(Value) if ok { return something } } return nil })) constant, ok := maybeConstant.Value().(Value) if ok { return constant, nil } else { return nil, NewNameError( constantNode.Name, context.String(), context.Class().String(), vm.stack.String(), ) } }
func interpretClassInContext( vm *vm, class ast.Class, context Value, ) (Value, error) { var ( value Value ok bool ) name := class.FullName() maybeTheValue := gomads.Maybe(func() interface{} { return vm.CurrentClasses[name] }).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentModules[name] })).OrSome(gomads.Maybe(func() interface{} { module, ok := vm.CurrentClasses[class.Namespace] if !ok { return nil } value, err := module.Constant(class.Name) if err != nil { return nil } return value })).OrSome(gomads.Maybe(func() interface{} { module, ok := vm.CurrentModules[class.Namespace] if !ok { return nil } value, err := module.Constant(class.Name) if err != nil { return nil } return value })).OrSome(gomads.Maybe(func() interface{} { if vm.currentModuleName == "" { return nil } parts := strings.Split(vm.currentModuleName, "::") count := len(parts) - 1 for index, _ := range parts { namespace := append(parts[0:(count-index)], name) nameToLookup := strings.Join(namespace, "::") maybe := gomads.Maybe(func() interface{} { return vm.CurrentClasses[nameToLookup] }).OrSome(gomads.Maybe(func() interface{} { return vm.CurrentModules[nameToLookup] })) something, ok := maybe.Value().(Value) if ok { return something } } return nil })).OrSome( NewNameError( name, context.String(), context.Class().String(), vm.stack.String(), ), ) value, ok = maybeTheValue.Value().(Value) if ok { return value, nil } else { return nil, value.(error) } }
func interpretBareReferenceInContext( vm *vm, ref ast.BareReference, context Value, ) (Value, error) { var name string = ref.Name var returnErr error maybe := gomads.Maybe(func() interface{} { m, err := vm.localVariableStack.Retrieve(name) if err == nil { return m } else { return nil } }).OrSome(gomads.Maybe(func() interface{} { m, ok := vm.ObjectSpace[name] if ok { return m } else { return nil } })).OrSome(gomads.Maybe(func() interface{} { m, ok := vm.CurrentClasses[name] if ok { return m } else { return nil } })).OrSome(gomads.Maybe(func() interface{} { m, ok := vm.CurrentModules[name] if ok { return m } else { return nil } })).OrSome(gomads.Maybe(func() interface{} { maybeMethod := context.Method(name) if maybeMethod == nil { return nil } value, err := maybeMethod.Execute(context, nil) if err != nil { returnErr = err return nil } else { return value } })) if returnErr != nil { return nil, returnErr } value, ok := maybe.Value().(Value) if ok { return value, nil } else { return nil, NewNameError( name, context.String(), context.Class().String(), vm.stack.String(), ) } }