1package main
2
3import "fmt"
4
5// renderExpr centralizes expression lowering; callers supply parameter, owned
6// field, or getter references. No expression decisions are left to templates.
7func renderExpr(n *Node, ref func(string) string, m *Module) (string, error) {
8 if n == nil {
9 return "", nil
10 }
11 switch n.Kind {
12 case "value":
13 return n.Text, nil
14 case "fieldref":
15 return ref(n.Text), nil
16 case "enumref":
17 e, owner := findEnum(m, n.Attr["ref"])
18 if e == nil {
19 return "", n.fail("unknown enum %s", n.Attr["ref"])
20 }
21 return "int(" + qualified(m, owner, e.Name+goName(n.Text)) + ")", nil
22 case "op", "unop", "popcount":
23 var parts []string
24 for _, c := range n.Children {
25 s, err := renderExpr(c, ref, m)
26 if err != nil {
27 return "", err
28 }
29 parts = append(parts, s)
30 }
31 if n.Kind == "popcount" {
32 return "bits.OnesCount(uint(" + parts[0] + "))", nil
33 }
34 if n.Kind == "unop" {
35 return "(^" + parts[0] + ")", nil
36 }
37 if len(parts) != 2 {
38 return "", n.fail("invalid binary expression")
39 }
40 return "(" + parts[0] + " " + n.Attr["op"] + " " + parts[1] + ")", nil
41 }
42 return "", fmt.Errorf("%s:%d: unsupported expression %s", n.File, n.Line, n.Kind)
43}