@@ -57,6 +57,11 @@ func (env *Env) interfaceToStarlarkValue(v interface{}) starlark.Value {
5757		return  starlark .None 
5858	case  error :
5959		return  starlark .String (v .Error ())
60+ 	case  reflect.Value :
61+ 		if  v .Type ().Kind () ==  reflect .Struct  {
62+ 			return  structAsStarlarkValue {v , env }
63+ 		}
64+ 		return  env .interfaceToStarlarkValue (v .Interface ())
6065	default :
6166		vval  :=  reflect .ValueOf (v )
6267		switch  vval .Type ().Kind () {
@@ -185,9 +190,48 @@ func (v structAsStarlarkValue) Attr(name string) (starlark.Value, error) {
185190	}
186191	r  :=  v .v .FieldByName (name )
187192	if  ! r .IsValid () {
188- 		return  starlark .None , fmt .Errorf ("no field named %q in %T" , name , v .v .Interface ())
193+ 		return  starlark .None , starlark . NoSuchAttrError ( fmt .Sprintf ("no field named %q in %T" , name , v .v .Interface () ))
189194	}
190- 	return  v .env .interfaceToStarlarkValue (r .Interface ()), nil 
195+ 	return  v .env .interfaceToStarlarkValue (r ), nil 
196+ }
197+ 
198+ func  (v  structAsStarlarkValue ) SetField (name  string , value  starlark.Value ) (err  error ) {
199+ 	defer  func () {
200+ 		// reflect.Value.SetInt, SetFloat, etc panic 
201+ 		ierr  :=  recover ()
202+ 		if  ierr  ==  nil  {
203+ 			return 
204+ 		}
205+ 		err , _  =  ierr .(error )
206+ 		if  err  ==  nil  {
207+ 			panic (ierr )
208+ 		}
209+ 		err  =  fmt .Errorf ("can not assign to %T.%q: %v" , v .v .Interface (), name , err )
210+ 	}()
211+ 	if  r , err  :=  v .valueAttr (name ); err  !=  nil  ||  r  !=  nil  {
212+ 		return  starlark .NoSuchAttrError (fmt .Sprintf ("no field named %s in %T" , name , v .v .Interface ()))
213+ 	}
214+ 	r  :=  v .v .FieldByName (name )
215+ 	if  ! r .IsValid () {
216+ 		return  starlark .NoSuchAttrError (fmt .Sprintf ("no field named %q in %T" , name , v .v .Interface ()))
217+ 	}
218+ 	switch  value  :=  value .(type ) {
219+ 	case  starlark.Int :
220+ 		n , ok  :=  value .Int64 ()
221+ 		if  ! ok  {
222+ 			return  fmt .Errorf ("can not assign big integer to %T.%q" , v .v .Interface (), name )
223+ 		}
224+ 		r .SetInt (n )
225+ 	case  starlark.Float :
226+ 		r .SetFloat (float64 (value ))
227+ 	case  starlark.String :
228+ 		r .SetString (value .GoString ())
229+ 	case  starlark.Bool :
230+ 		r .SetBool (bool (value ))
231+ 	default :
232+ 		return  fmt .Errorf ("can not assign value of type %T to %T.%q" , value , v .v .Interface (), name )
233+ 	}
234+ 	return  nil 
191235}
192236
193237func  (v  structAsStarlarkValue ) valueAttr (name  string ) (starlark.Value , error ) {
0 commit comments