Mercurial Hosting > d2o
comparison icf/icf.go @ 6:54ab94198677
abstract mixins + building sctipt + documentation
| author | Atarwn Gard <a@qwa.su> |
|---|---|
| date | Tue, 10 Mar 2026 10:22:02 +0500 |
| parents | dacc92aae6d5 |
| children | 2ffb8028ccbb |
comparison
equal
deleted
inserted
replaced
| 5:07b6f06899e0 | 6:54ab94198677 |
|---|---|
| 15 Key string | 15 Key string |
| 16 Args []string | 16 Args []string |
| 17 } | 17 } |
| 18 | 18 |
| 19 type Config struct { | 19 type Config struct { |
| 20 vars map[string]string | 20 vars map[string]string |
| 21 abstract map[string][]Directive | 21 abstract map[string][]Directive |
| 22 Blocks []ParsedBlock | 22 abstractMixin map[string]string // mixin name for each abstract block |
| 23 Blocks []ParsedBlock | |
| 23 } | 24 } |
| 24 | 25 |
| 25 type ParsedBlock struct { | 26 type ParsedBlock struct { |
| 26 ID string | 27 ID string |
| 27 Mixin string | 28 Mixin string |
| 101 } | 102 } |
| 102 flush() | 103 flush() |
| 103 | 104 |
| 104 // --- Pass 3: separate abstract from concrete, apply var substitution --- | 105 // --- Pass 3: separate abstract from concrete, apply var substitution --- |
| 105 c := &Config{ | 106 c := &Config{ |
| 106 vars: vars, | 107 vars: vars, |
| 107 abstract: make(map[string][]Directive), | 108 abstract: make(map[string][]Directive), |
| 109 abstractMixin: make(map[string]string), | |
| 108 } | 110 } |
| 109 | 111 |
| 110 for _, rb := range raws { | 112 for _, rb := range raws { |
| 111 dirs := make([]Directive, len(rb.directives)) | 113 dirs := make([]Directive, len(rb.directives)) |
| 112 for i, rd := range rb.directives { | 114 for i, rd := range rb.directives { |
| 116 } | 118 } |
| 117 dirs[i] = Directive{Key: rd.key, Args: args} | 119 dirs[i] = Directive{Key: rd.key, Args: args} |
| 118 } | 120 } |
| 119 | 121 |
| 120 if strings.HasPrefix(rb.id, "@") { | 122 if strings.HasPrefix(rb.id, "@") { |
| 121 c.abstract[rb.id[1:]] = dirs | 123 name := rb.id[1:] |
| 124 c.abstract[name] = dirs | |
| 125 if rb.mixin != "" { | |
| 126 c.abstractMixin[name] = rb.mixin | |
| 127 } | |
| 122 } else { | 128 } else { |
| 123 c.Blocks = append(c.Blocks, ParsedBlock{ | 129 c.Blocks = append(c.Blocks, ParsedBlock{ |
| 124 ID: rb.id, | 130 ID: rb.id, |
| 125 Mixin: rb.mixin, | 131 Mixin: rb.mixin, |
| 126 Directives: dirs, | 132 Directives: dirs, |
| 183 // ResolveBlock merges mixin directives (lower priority) with block directives, | 189 // ResolveBlock merges mixin directives (lower priority) with block directives, |
| 184 // then substitutes capture variables. | 190 // then substitutes capture variables. |
| 185 func (c *Config) ResolveBlock(b ParsedBlock, caps map[string]string) []Directive { | 191 func (c *Config) ResolveBlock(b ParsedBlock, caps map[string]string) []Directive { |
| 186 var merged []Directive | 192 var merged []Directive |
| 187 if b.Mixin != "" { | 193 if b.Mixin != "" { |
| 188 merged = append(merged, c.abstract[b.Mixin]...) | 194 merged = append(merged, c.resolveAbstract(b.Mixin, make(map[string]bool))...) |
| 189 } | 195 } |
| 190 merged = append(merged, b.Directives...) | 196 merged = append(merged, b.Directives...) |
| 191 | 197 |
| 192 if len(caps) == 0 { | 198 if len(caps) == 0 { |
| 193 return merged | 199 return merged |
| 204 } | 210 } |
| 205 } | 211 } |
| 206 return out | 212 return out |
| 207 } | 213 } |
| 208 | 214 |
| 215 // resolveAbstract recursively expands an abstract block and its mixin chain. | |
| 216 // visited guards against circular references. | |
| 217 func (c *Config) resolveAbstract(name string, visited map[string]bool) []Directive { | |
| 218 if visited[name] { | |
| 219 return nil | |
| 220 } | |
| 221 visited[name] = true | |
| 222 | |
| 223 var out []Directive | |
| 224 if parent, ok := c.abstractMixin[name]; ok { | |
| 225 out = append(out, c.resolveAbstract(parent, visited)...) | |
| 226 } | |
| 227 out = append(out, c.abstract[name]...) | |
| 228 return out | |
| 229 } | |
| 230 | |
| 209 // makeSubst returns a function that substitutes $VAR in s, | 231 // makeSubst returns a function that substitutes $VAR in s, |
| 210 // checking caps first, then vars. | 232 // checking caps first, then vars. |
| 211 func makeSubst(vars map[string]string) func(s string, caps map[string]string) string { | 233 func makeSubst(vars map[string]string) func(s string, caps map[string]string) string { |
| 212 return func(s string, caps map[string]string) string { | 234 return func(s string, caps map[string]string) string { |
| 213 if !strings.Contains(s, "$") { | 235 if !strings.Contains(s, "$") { |
