Source file
src/tawesoft.co.uk/go/glcaps/tag.go
Documentation:
src/tawesoft.co.uk/go/glcaps/tag.go
1 package glcaps
2
3 import (
4 "fmt"
5 "strconv"
6 "strings"
7 )
8
9 func operationStringEq (a string, b string) bool { return a == b }
10 func operationStringNeq (a string, b string) bool { return a != b }
11
12 type command interface{
13 evalBool (b *Binding, extensions Extensions) bool
14 evalInt (b *Binding, extensions Extensions) int
15 evalFloat (b *Binding, extensions Extensions) float32
16 evalString(b *Binding, extensions Extensions) string
17 hasBoolRepresentation() bool
18 hasIntRepresentation() bool
19 hasFloatRepresentation() bool
20 hasStringRepresentation() bool
21 }
22
23 type requirement interface{
24 evalBool (field string, result bool) error
25 evalInt (field string, result int) error
26 evalFloat (field string, result float32) error
27 evalString(field string, result string) error
28 }
29
30 type tag struct {
31 command command
32 requirements []requirement
33 }
34
35
36
37 type requirementRequired struct {}
38
39 func (r requirementRequired) evalBool(field string, result bool) error {
40 if result { return nil }
41 return fmt.Errorf("%s is required", field)
42 }
43
44 func (r requirementRequired) evalInt(field string, result int) error {
45 panic("not an int")
46 }
47
48 func (r requirementRequired) evalFloat(field string, result float32) error {
49 panic("not a float")
50 }
51
52 func (r requirementRequired) evalString(field string, result string) error {
53 if len(result) > 0 { return nil }
54 return fmt.Errorf("%s is required", field)
55 }
56
57
58
59 type requirementComparison struct {
60 constant string
61 symbol string
62 operationi func(int, int) bool
63 operationf func(float32, float32) bool
64 operations func(string, string) bool
65 }
66
67 func (r requirementComparison) evalBool(field string, result bool) error {
68 panic("not a bool")
69 }
70
71 func (r requirementComparison) evalInt(field string, result int) error {
72 var i, err = strconv.ParseInt(r.constant, 10, 32)
73 if err != nil { panic("not an integer constant") }
74
75 if r.operationi(result, int(i)) { return nil }
76 return fmt.Errorf("%s is %d but must be %s %s", field, result, r.symbol, r.constant)
77 }
78
79 func (r requirementComparison) evalFloat(field string, result float32) error {
80 var f, err = strconv.ParseFloat(r.constant, 32)
81 if err != nil { panic("not a float constant") }
82
83 if r.operationf(result, float32(f)) { return nil }
84 return fmt.Errorf("%s is %.2f but must be %s %s", field, result, r.symbol, r.constant)
85 }
86
87 func (r requirementComparison) evalString(field string, result string) error {
88 if r.operations(result, r.constant) { return nil }
89 return fmt.Errorf("%s is %s but must be %s %s", field, result, r.symbol, r.constant)
90 }
91
92
93
94 type commandValue struct {
95 value string
96 }
97
98 func (c commandValue) evalBool(_ *Binding, _ Extensions) bool {
99 switch c.value {
100 case "true": return true
101 case "false": return false
102 default: panic(fmt.Sprintf("not a boolean: '%s'", c.value))
103 }
104 }
105
106 func (c commandValue) evalInt(_ *Binding, _ Extensions) int {
107 var result, err = strconv.ParseInt(c.value, 10, 32)
108 if err != nil { panic(fmt.Sprintf("not an integer: '%s'", c.value)) }
109 return int(result)
110 }
111
112 func (c commandValue) evalFloat(_ *Binding, _ Extensions) float32 {
113 var result, err = strconv.ParseFloat(c.value, 32)
114 if err != nil { panic(fmt.Sprintf("not a float: '%s'", c.value)) }
115 return float32(result)
116 }
117
118 func (c commandValue) evalString(_ *Binding, _ Extensions) string {
119 return c.value
120 }
121
122 func (c commandValue) hasBoolRepresentation() bool {
123 switch c.value {
124 case "true": return true
125 case "false": return true
126 default: return false
127 }
128 }
129
130 func (c commandValue) hasIntRepresentation() bool {
131 var _, err = strconv.ParseInt(c.value, 10, 32)
132 return err == nil
133 }
134
135 func (c commandValue) hasFloatRepresentation() bool {
136 var hasRadix = (strings.IndexByte(c.value, '.') >= 0)
137 var _, err = strconv.ParseFloat(c.value, 32)
138 return err == nil && hasRadix
139 }
140
141 func (c commandValue) hasStringRepresentation() bool {
142 return true
143 }
144
145
146
147 type commandBinaryBoolean struct {
148 a command
149 b command
150 operation func(bool, bool) bool
151 }
152
153 func (c commandBinaryBoolean) evalBool(b *Binding, e Extensions) bool {
154 return c.operation(c.a.evalBool(b, e), c.b.evalBool(b, e))
155 }
156
157 func (c commandBinaryBoolean) evalInt(b *Binding, _ Extensions) int {
158 panic("not an integer")
159 }
160
161 func (c commandBinaryBoolean) evalFloat(b *Binding, _ Extensions) float32 {
162 panic("not a float")
163 }
164
165 func (c commandBinaryBoolean) evalString(_ *Binding, _ Extensions) string {
166 panic("not a string")
167 }
168
169 func (c commandBinaryBoolean) hasBoolRepresentation() bool {
170 return true
171 }
172
173 func (c commandBinaryBoolean) hasIntRepresentation() bool {
174 return false
175 }
176
177 func (c commandBinaryBoolean) hasFloatRepresentation() bool {
178 return false
179 }
180
181 func (c commandBinaryBoolean) hasStringRepresentation() bool {
182 return false
183 }
184
185
186
187 type commandNot struct {
188 inner command
189 }
190
191 func (c commandNot) evalBool(b *Binding, e Extensions) bool {
192 return !c.inner.evalBool(b, e)
193 }
194
195 func (c commandNot) evalInt(b *Binding, _ Extensions) int {
196 panic("not an integer")
197 }
198
199 func (c commandNot) evalFloat(b *Binding, _ Extensions) float32 {
200 panic("not a float")
201 }
202
203 func (c commandNot) evalString(b *Binding, _ Extensions) string {
204 panic("not a string")
205 }
206
207 func (c commandNot) hasBoolRepresentation() bool {
208 return true
209 }
210
211 func (c commandNot) hasIntRepresentation() bool {
212 return false
213 }
214
215 func (c commandNot) hasFloatRepresentation() bool {
216 return false
217 }
218
219 func (c commandNot) hasStringRepresentation() bool {
220 return false
221 }
222
223
224
225 type commandCompare struct {
226 a command
227 b command
228 operationi func(int, int) bool
229 operationf func(float32, float32) bool
230 operations func(string, string) bool
231 }
232
233 func (c commandCompare) evalBool(b *Binding, e Extensions) bool {
234 if c.a.hasFloatRepresentation() && c.b.hasFloatRepresentation() {
235 return c.operationf(c.a.evalFloat(b, e), c.b.evalFloat(b, e))
236 } else if c.a.hasIntRepresentation() && c.b.hasIntRepresentation() {
237 return c.operationi(c.a.evalInt(b, e), c.b.evalInt(b, e))
238 } else if c.a.hasStringRepresentation() && c.b.hasStringRepresentation() {
239 if c.operations != nil {
240 return c.operations(c.a.evalString(b, e), c.b.evalString(b, e))
241 } else {
242 panic(fmt.Sprintf("string operation not defined for this comparison"))
243 }
244 } else {
245 panic(fmt.Sprintf("cannot compare mismatched types (%+v and %+v)", c.a, c.b))
246 }
247 }
248
249 func (c commandCompare) evalInt(b *Binding, e Extensions) int {
250 panic("not an integer")
251 }
252
253 func (c commandCompare) evalFloat(b *Binding, e Extensions) float32 {
254 panic("not a float")
255 }
256
257 func (c commandCompare) evalString(b *Binding, e Extensions) string {
258 panic("not a string")
259 }
260
261 func (c commandCompare) hasBoolRepresentation() bool {
262 return false
263 }
264
265 func (c commandCompare) hasIntRepresentation() bool {
266 return c.a.hasIntRepresentation() && c.b.hasIntRepresentation()
267 }
268
269 func (c commandCompare) hasFloatRepresentation() bool {
270 return c.a.hasFloatRepresentation() && c.b.hasFloatRepresentation()
271 }
272
273 func (c commandCompare) hasStringRepresentation() bool {
274 return c.a.hasStringRepresentation() && c.b.hasStringRepresentation()
275 }
276
277
278
279 type commandExt struct {
280 name string
281 }
282
283 func (c commandExt) evalBool(b *Binding, e Extensions) bool {
284 return e.Contains(c.name)
285 }
286
287 func (c commandExt) evalInt(b *Binding, e Extensions) int {
288 panic("not an integer")
289 }
290
291 func (c commandExt) evalFloat(b *Binding, e Extensions) float32 {
292 panic("not a float")
293 }
294
295 func (c commandExt) evalString(b *Binding, e Extensions) string {
296 panic("not a string")
297 }
298
299 func (c commandExt) hasBoolRepresentation() bool {
300 return true
301 }
302
303 func (c commandExt) hasIntRepresentation() bool {
304 return false
305 }
306
307 func (c commandExt) hasFloatRepresentation() bool {
308 return false
309 }
310
311 func (c commandExt) hasStringRepresentation() bool {
312 return false
313 }
314
315
316
317 type commandGetIntegerv struct {
318 name string
319 }
320
321 func (c commandGetIntegerv) evalBool(b *Binding, e Extensions) bool {
322 panic("not a bool")
323 }
324
325 func (c commandGetIntegerv) evalInt(b *Binding, e Extensions) int {
326 var result int32
327 var id, exists = glconstants[c.name]
328 if !exists { return 0 }
329 b.GetIntegerv(id, &result)
330 return int(result)
331 }
332
333 func (c commandGetIntegerv) evalFloat(b *Binding, e Extensions) float32 {
334 panic("not a float")
335 }
336
337 func (c commandGetIntegerv) evalString(b *Binding, e Extensions) string {
338 panic("not a string")
339 }
340
341 func (c commandGetIntegerv) hasBoolRepresentation() bool {
342 return false
343 }
344
345 func (c commandGetIntegerv) hasIntRepresentation() bool {
346 return true
347 }
348
349 func (c commandGetIntegerv) hasFloatRepresentation() bool {
350 return false
351 }
352
353 func (c commandGetIntegerv) hasStringRepresentation() bool {
354 return false
355 }
356
357
358
359 type commandGetFloatv struct {
360 name string
361 }
362
363 func (c commandGetFloatv) evalBool(b *Binding, e Extensions) bool {
364 panic("not a bool")
365 }
366
367 func (c commandGetFloatv) evalInt(b *Binding, e Extensions) int {
368 panic("not an int")
369 }
370
371 func (c commandGetFloatv) evalFloat(b *Binding, e Extensions) float32 {
372 var result float32
373 var id, exists = glconstants[c.name]
374 if !exists { return 0.0 }
375 b.GetFloatv(id, &result)
376 return result
377 }
378
379 func (c commandGetFloatv) evalString(b *Binding, e Extensions) string {
380 panic("not a string")
381 }
382
383 func (c commandGetFloatv) hasBoolRepresentation() bool {
384 return false
385 }
386
387 func (c commandGetFloatv) hasIntRepresentation() bool {
388 return false
389 }
390
391 func (c commandGetFloatv) hasFloatRepresentation() bool {
392 return true
393 }
394
395 func (c commandGetFloatv) hasStringRepresentation() bool {
396 return false
397 }
398
399
400
401 type commandGetString struct {
402 name string
403 }
404
405 func (c commandGetString) evalBool(b *Binding, e Extensions) bool {
406 panic("not a bool")
407 }
408
409 func (c commandGetString) evalInt(b *Binding, e Extensions) int {
410 panic("not an int")
411 }
412
413 func (c commandGetString) evalFloat(b *Binding, e Extensions) float32 {
414 panic("not a float")
415 }
416
417 func (c commandGetString) evalString(b *Binding, e Extensions) string {
418 var id, exists = glconstants[c.name]
419 if !exists { return "" }
420 return b.GetString(id)
421 }
422
423 func (c commandGetString) hasBoolRepresentation() bool {
424 return false
425 }
426
427 func (c commandGetString) hasIntRepresentation() bool {
428 return false
429 }
430
431 func (c commandGetString) hasFloatRepresentation() bool {
432 return false
433 }
434
435 func (c commandGetString) hasStringRepresentation() bool {
436 return true
437 }
438
439
440
441 type commandIf struct {
442 clause command
443 implication command
444 otherwise command
445 }
446
447 func (c commandIf) evalBool(b *Binding, e Extensions) bool {
448 if !c.hasBoolRepresentation() { panic(fmt.Sprintf("both clauses of %+v must have a bool representation", c)) }
449 if c.clause.evalBool(b, e) {
450 return c.implication.evalBool(b, e)
451 } else {
452 return c.otherwise.evalBool(b, e)
453 }
454 }
455
456 func (c commandIf) evalInt(b *Binding, e Extensions) int {
457 if !c.hasIntRepresentation() { panic(fmt.Sprintf("both clauses of %+v must have an int representation", c)) }
458 if c.clause.evalBool(b, e) {
459 return c.implication.evalInt(b, e)
460 } else {
461 return c.otherwise.evalInt(b, e)
462 }
463 }
464
465 func (c commandIf) evalFloat(b *Binding, e Extensions) float32 {
466 if !c.hasFloatRepresentation() { panic(fmt.Sprintf("both clauses of %+v must have an int representation", c)) }
467 if c.clause.evalBool(b, e) {
468 return c.implication.evalFloat(b, e)
469 } else {
470 return c.otherwise.evalFloat(b, e)
471 }
472 }
473
474 func (c commandIf) evalString(b *Binding, e Extensions) string {
475 if !c.hasStringRepresentation() { panic(fmt.Sprintf("both clauses of %+v must have a string representation", c)) }
476 if c.clause.evalBool(b, e) {
477 return c.implication.evalString(b, e)
478 } else {
479 return c.otherwise.evalString(b, e)
480 }
481 }
482
483 func (c commandIf) hasBoolRepresentation() bool {
484 return c.implication.hasBoolRepresentation() && c.otherwise.hasBoolRepresentation()
485 }
486
487 func (c commandIf) hasIntRepresentation() bool {
488 return c.implication.hasIntRepresentation() && c.otherwise.hasIntRepresentation()
489 }
490
491 func (c commandIf) hasFloatRepresentation() bool {
492 return c.implication.hasFloatRepresentation() && c.otherwise.hasFloatRepresentation()
493 }
494
495 func (c commandIf) hasStringRepresentation() bool {
496 return c.implication.hasStringRepresentation() && c.otherwise.hasStringRepresentation()
497 }
498
View as plain text