| 1 | ## our_shell: ysh
 | 
| 2 | ## oils_failures_allowed: 1
 | 
| 3 | 
 | 
| 4 | #### Local place
 | 
| 5 | 
 | 
| 6 | # Work around stdin buffering issue with read --line
 | 
| 7 | #
 | 
| 8 | # The framework test/sh_spec.py uses echo "$code_string" | $SH
 | 
| 9 | #
 | 
| 10 | # But then we have TWO different values of file descriptor 0 (stdin)
 | 
| 11 | #
 | 
| 12 | # - the pipe with the code
 | 
| 13 | # - the pipe created in th shell for echo zzz | read --line
 | 
| 14 | #
 | 
| 15 | # Shells read one line at a time, but read --line explicitly avoids this.
 | 
| 16 | #
 | 
| 17 | # TODO: I wonder if we should consider outlawing read --line when stdin has code
 | 
| 18 | # Only allow it for:
 | 
| 19 | #
 | 
| 20 | # $SH -c 'echo hi'
 | 
| 21 | # $SH myscript.sh
 | 
| 22 | #
 | 
| 23 | # There could be a warning like read --line --no-fighting or something.
 | 
| 24 | 
 | 
| 25 | cat >tmp.sh <<'EOF'
 | 
| 26 | func f(place) {
 | 
| 27 |   var x = 'f'
 | 
| 28 |   echo zzz | read --all (place)
 | 
| 29 |   echo "f x=$x"
 | 
| 30 | }
 | 
| 31 | 
 | 
| 32 | func fillPlace(place) {
 | 
| 33 |   var x = 'fillPlace'
 | 
| 34 |   call f(place)
 | 
| 35 |   echo "fillPlace x=$x"
 | 
| 36 | }
 | 
| 37 | 
 | 
| 38 | proc p {
 | 
| 39 |   var x = 'hi'
 | 
| 40 |   call fillPlace(&x)
 | 
| 41 |   echo "p x=$x"
 | 
| 42 | }
 | 
| 43 | 
 | 
| 44 | x=global
 | 
| 45 | 
 | 
| 46 | p
 | 
| 47 | 
 | 
| 48 | echo "global x=$x"
 | 
| 49 | EOF
 | 
| 50 | 
 | 
| 51 | $SH tmp.sh
 | 
| 52 | 
 | 
| 53 | ## STDOUT:
 | 
| 54 | f x=f
 | 
| 55 | fillPlace x=fillPlace
 | 
| 56 | p x=zzz
 | 
| 57 | 
 | 
| 58 | global x=global
 | 
| 59 | ## END
 | 
| 60 | 
 | 
| 61 | #### place->setValue()
 | 
| 62 | 
 | 
| 63 | func f(place) {
 | 
| 64 |   var x = 'f'
 | 
| 65 |   call place->setValue('zzz')
 | 
| 66 |   echo "f x=$x"
 | 
| 67 | }
 | 
| 68 | 
 | 
| 69 | func fillPlace(place) {
 | 
| 70 |   var x = 'fillPlace'
 | 
| 71 |   call f(place)
 | 
| 72 |   echo "fillPlace x=$x"
 | 
| 73 | }
 | 
| 74 | 
 | 
| 75 | proc p {
 | 
| 76 |   var x = 'hi'
 | 
| 77 |   call fillPlace(&x)
 | 
| 78 |   echo "p x=$x"
 | 
| 79 | }
 | 
| 80 | 
 | 
| 81 | x=global
 | 
| 82 | 
 | 
| 83 | p
 | 
| 84 | echo "global x=$x"
 | 
| 85 | 
 | 
| 86 | ## STDOUT:
 | 
| 87 | f x=f
 | 
| 88 | fillPlace x=fillPlace
 | 
| 89 | p x=zzz
 | 
| 90 | global x=global
 | 
| 91 | ## END
 | 
| 92 | 
 | 
| 93 | #### Places can't dangle; they should be passed UP the stakc only
 | 
| 94 | 
 | 
| 95 | func f() {
 | 
| 96 |   var f_local = null
 | 
| 97 |   return (&f_local)
 | 
| 98 | }
 | 
| 99 | 
 | 
| 100 | func g() {
 | 
| 101 |   # This place is now INVALID!
 | 
| 102 |   var place = f()
 | 
| 103 | 
 | 
| 104 |   # Should fail when we try to use the place
 | 
| 105 |   echo zzz | read --all (place)
 | 
| 106 | 
 | 
| 107 |   # This should also fail
 | 
| 108 |   # call place->setValue('zzz')
 | 
| 109 | 
 | 
| 110 | }
 | 
| 111 | 
 | 
| 112 | call g()
 | 
| 113 | 
 | 
| 114 | echo done
 | 
| 115 | 
 | 
| 116 | ## status: 1
 | 
| 117 | ## STDOUT:
 | 
| 118 | ## END
 | 
| 119 | 
 | 
| 120 | 
 | 
| 121 | #### Container Place (Dict)
 | 
| 122 | 
 | 
| 123 | var d = {key: 'hi'}
 | 
| 124 | 
 | 
| 125 | echo zzz | read --all (&d.key)
 | 
| 126 | 
 | 
| 127 | # I guess this works
 | 
| 128 | echo newkey | read --all (&d.newkey)
 | 
| 129 | 
 | 
| 130 | echo key=$[d.key]
 | 
| 131 | echo key=$[d.newkey]
 | 
| 132 | 
 | 
| 133 | ## STDOUT:
 | 
| 134 | ## END
 | 
| 135 | 
 | 
| 136 | 
 |