Mercurial Hosting > d2o
diff 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 |
line wrap: on
line diff
--- a/icf/icf.go Mon Mar 09 03:35:47 2026 +0500 +++ b/icf/icf.go Tue Mar 10 10:22:02 2026 +0500 @@ -17,9 +17,10 @@ } type Config struct { - vars map[string]string - abstract map[string][]Directive - Blocks []ParsedBlock + vars map[string]string + abstract map[string][]Directive + abstractMixin map[string]string // mixin name for each abstract block + Blocks []ParsedBlock } type ParsedBlock struct { @@ -103,8 +104,9 @@ // --- Pass 3: separate abstract from concrete, apply var substitution --- c := &Config{ - vars: vars, - abstract: make(map[string][]Directive), + vars: vars, + abstract: make(map[string][]Directive), + abstractMixin: make(map[string]string), } for _, rb := range raws { @@ -118,7 +120,11 @@ } if strings.HasPrefix(rb.id, "@") { - c.abstract[rb.id[1:]] = dirs + name := rb.id[1:] + c.abstract[name] = dirs + if rb.mixin != "" { + c.abstractMixin[name] = rb.mixin + } } else { c.Blocks = append(c.Blocks, ParsedBlock{ ID: rb.id, @@ -185,7 +191,7 @@ func (c *Config) ResolveBlock(b ParsedBlock, caps map[string]string) []Directive { var merged []Directive if b.Mixin != "" { - merged = append(merged, c.abstract[b.Mixin]...) + merged = append(merged, c.resolveAbstract(b.Mixin, make(map[string]bool))...) } merged = append(merged, b.Directives...) @@ -206,6 +212,22 @@ return out } +// resolveAbstract recursively expands an abstract block and its mixin chain. +// visited guards against circular references. +func (c *Config) resolveAbstract(name string, visited map[string]bool) []Directive { + if visited[name] { + return nil + } + visited[name] = true + + var out []Directive + if parent, ok := c.abstractMixin[name]; ok { + out = append(out, c.resolveAbstract(parent, visited)...) + } + out = append(out, c.abstract[name]...) + return out +} + // makeSubst returns a function that substitutes $VAR in s, // checking caps first, then vars. func makeSubst(vars map[string]string) func(s string, caps map[string]string) string {
