| 1 | # Hay Metaprogramming
 | 
| 2 | 
 | 
| 3 | #### Conditional Inside Blocks
 | 
| 4 | shopt --set oil:all
 | 
| 5 | 
 | 
| 6 | hay define Rule
 | 
| 7 | 
 | 
| 8 | const DEBUG = true
 | 
| 9 | 
 | 
| 10 | Rule one {
 | 
| 11 |   if (DEBUG) {
 | 
| 12 |     deps = 'foo'
 | 
| 13 |   } else {
 | 
| 14 |     deps = 'bar'
 | 
| 15 |   }
 | 
| 16 | }
 | 
| 17 | 
 | 
| 18 | json write (_hay()) | jq '.children[0]' > actual.txt
 | 
| 19 | 
 | 
| 20 | diff -u - actual.txt <<EOF
 | 
| 21 | {
 | 
| 22 |   "type": "Rule",
 | 
| 23 |   "args": [
 | 
| 24 |     "one"
 | 
| 25 |   ],
 | 
| 26 |   "children": [],
 | 
| 27 |   "attrs": {
 | 
| 28 |     "deps": "foo"
 | 
| 29 |   }
 | 
| 30 | }
 | 
| 31 | EOF
 | 
| 32 | 
 | 
| 33 | ## STDOUT:
 | 
| 34 | ## END
 | 
| 35 | 
 | 
| 36 | 
 | 
| 37 | #### Conditional Outside Block
 | 
| 38 | shopt --set oil:all
 | 
| 39 | 
 | 
| 40 | hay define Rule
 | 
| 41 | 
 | 
| 42 | const DEBUG = true
 | 
| 43 | 
 | 
| 44 | if (DEBUG) {
 | 
| 45 |   Rule two {
 | 
| 46 |     deps = 'spam'
 | 
| 47 |   } 
 | 
| 48 | } else {
 | 
| 49 |   Rule two {
 | 
| 50 |     deps = 'bar'
 | 
| 51 |   } 
 | 
| 52 | }
 | 
| 53 | 
 | 
| 54 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
 | 
| 55 | 
 | 
| 56 | diff -u - actual.txt <<EOF
 | 
| 57 | {
 | 
| 58 |   "deps": "spam"
 | 
| 59 | }
 | 
| 60 | EOF
 | 
| 61 | 
 | 
| 62 | ## STDOUT:
 | 
| 63 | ## END
 | 
| 64 | 
 | 
| 65 | 
 | 
| 66 | #### Iteration Inside Block
 | 
| 67 | shopt --set oil:all
 | 
| 68 | 
 | 
| 69 | hay define Rule
 | 
| 70 | 
 | 
| 71 | Rule foo {
 | 
| 72 |   var d = {}
 | 
| 73 |   # private var with _
 | 
| 74 |   for name_ in spam eggs ham {
 | 
| 75 |     setvar d[name_] = true
 | 
| 76 |   }
 | 
| 77 | }
 | 
| 78 | 
 | 
| 79 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
 | 
| 80 | 
 | 
| 81 | # For loop name leaks!  Might want to make it "name_" instead!
 | 
| 82 | 
 | 
| 83 | #cat actual.txt
 | 
| 84 | 
 | 
| 85 | diff -u - actual.txt <<EOF
 | 
| 86 | {
 | 
| 87 |   "d": {
 | 
| 88 |     "spam": true,
 | 
| 89 |     "eggs": true,
 | 
| 90 |     "ham": true
 | 
| 91 |   }
 | 
| 92 | }
 | 
| 93 | EOF
 | 
| 94 | 
 | 
| 95 | 
 | 
| 96 | ## STDOUT:
 | 
| 97 | ## END
 | 
| 98 | 
 | 
| 99 | 
 | 
| 100 | #### Iteration Outside Block
 | 
| 101 | shopt --set oil:all
 | 
| 102 | 
 | 
| 103 | hay define Rule
 | 
| 104 | 
 | 
| 105 | for name in spam eggs ham {
 | 
| 106 |   Rule $name {
 | 
| 107 |     path = "/usr/bin/$name"
 | 
| 108 |   }
 | 
| 109 | }
 | 
| 110 | 
 | 
| 111 | json write (_hay()) | jq '.children[].attrs' > actual.txt
 | 
| 112 | 
 | 
| 113 | diff -u - actual.txt <<EOF
 | 
| 114 | {
 | 
| 115 |   "path": "/usr/bin/spam"
 | 
| 116 | }
 | 
| 117 | {
 | 
| 118 |   "path": "/usr/bin/eggs"
 | 
| 119 | }
 | 
| 120 | {
 | 
| 121 |   "path": "/usr/bin/ham"
 | 
| 122 | }
 | 
| 123 | EOF
 | 
| 124 | 
 | 
| 125 | ## STDOUT:
 | 
| 126 | ## END
 | 
| 127 | 
 | 
| 128 | 
 | 
| 129 | #### Proc Inside Block
 | 
| 130 | shopt --set oil:all
 | 
| 131 | 
 | 
| 132 | hay define rule  # lower case allowed
 | 
| 133 | 
 | 
| 134 | proc p(name; out) {
 | 
| 135 |   echo 'p'
 | 
| 136 |   call out->setValue(name)
 | 
| 137 | }
 | 
| 138 | 
 | 
| 139 | rule hello {
 | 
| 140 |   var eggs = ''
 | 
| 141 |   var bar = ''
 | 
| 142 | 
 | 
| 143 |   p spam (&eggs)
 | 
| 144 |   p foo (&bar)
 | 
| 145 | }
 | 
| 146 | 
 | 
| 147 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
 | 
| 148 | 
 | 
| 149 | diff -u - actual.txt <<EOF
 | 
| 150 | {
 | 
| 151 |   "eggs": "spam",
 | 
| 152 |   "bar": "foo"
 | 
| 153 | }
 | 
| 154 | EOF
 | 
| 155 | 
 | 
| 156 | ## STDOUT:
 | 
| 157 | p
 | 
| 158 | p
 | 
| 159 | ## END
 | 
| 160 | 
 | 
| 161 | 
 | 
| 162 | 
 | 
| 163 | #### Proc That Defines Block
 | 
| 164 | shopt --set oil:all
 | 
| 165 | 
 | 
| 166 | hay define Rule
 | 
| 167 | 
 | 
| 168 | proc myrule(name) {
 | 
| 169 | 
 | 
| 170 |   # Each haynode has its own scope.  But then it can't see the args!  Oops.
 | 
| 171 |   # Is there a better way to do this?
 | 
| 172 | 
 | 
| 173 |   shopt --set dynamic_scope {
 | 
| 174 |     Rule $name {
 | 
| 175 |       path = "/usr/bin/$name"
 | 
| 176 |     }
 | 
| 177 |   }
 | 
| 178 | }
 | 
| 179 | 
 | 
| 180 | myrule spam
 | 
| 181 | myrule eggs
 | 
| 182 | myrule ham
 | 
| 183 | 
 | 
| 184 | json write (_hay()) | jq '.children[].attrs' > actual.txt
 | 
| 185 | 
 | 
| 186 | diff -u - actual.txt <<EOF
 | 
| 187 | {
 | 
| 188 |   "path": "/usr/bin/spam"
 | 
| 189 | }
 | 
| 190 | {
 | 
| 191 |   "path": "/usr/bin/eggs"
 | 
| 192 | }
 | 
| 193 | {
 | 
| 194 |   "path": "/usr/bin/ham"
 | 
| 195 | }
 | 
| 196 | EOF
 | 
| 197 | 
 | 
| 198 | ## STDOUT:
 | 
| 199 | ## END
 | 
| 200 | 
 |