diff --git a/src/compiler/eachFunction.go b/src/compiler/eachFunction.go index 44bc00e..9ffa2e9 100644 --- a/src/compiler/eachFunction.go +++ b/src/compiler/eachFunction.go @@ -10,7 +10,7 @@ func (r *Result) eachFunction(caller *core.Function, traversed map[*core.Functio call(caller) traversed[caller] = true - for _, function := range caller.Dependencies { + for function := range caller.Dependencies.All() { if traversed[function] { continue } diff --git a/src/core/CompileDelete.go b/src/core/CompileDelete.go index b834d06..131a9d0 100644 --- a/src/core/CompileDelete.go +++ b/src/core/CompileDelete.go @@ -26,6 +26,6 @@ func (f *Function) CompileDelete(root *expression.Expression) error { f.BeforeCall() f.Label(asm.CALL, asm.Label{Name: "mem.free", Type: asm.FunctionLabel}) f.AfterCall(f.CPU.Input[:2]) - f.Dependencies = append(f.Dependencies, free) + f.Dependencies.Add(free) return nil } diff --git a/src/core/CompileNew.go b/src/core/CompileNew.go index 6d2ae30..c4b74bf 100644 --- a/src/core/CompileNew.go +++ b/src/core/CompileNew.go @@ -49,6 +49,6 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) { f.BeforeCall() f.Label(asm.CALL, asm.Label{Name: "mem.alloc", Type: asm.FunctionLabel}) f.AfterCall(f.CPU.Input[:1]) - f.Dependencies = append(f.Dependencies, alloc) + f.Dependencies.Add(alloc) return &types.Pointer{To: typ}, nil } diff --git a/src/core/EvaluateDot.go b/src/core/EvaluateDot.go index 3bc55c2..bed4420 100644 --- a/src/core/EvaluateDot.go +++ b/src/core/EvaluateDot.go @@ -76,7 +76,7 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error) function, exists := f.All.Functions[label] if exists { - f.Dependencies = append(f.Dependencies, function) + f.Dependencies.Add(function) value := &eval.Label{ Typ: types.AnyPointer, diff --git a/src/core/EvaluateToken.go b/src/core/EvaluateToken.go index 0b1aa30..991089e 100644 --- a/src/core/EvaluateToken.go +++ b/src/core/EvaluateToken.go @@ -46,7 +46,7 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) { function, exists := f.All.Functions[uniqueName] if exists { - f.Dependencies = append(f.Dependencies, function) + f.Dependencies.Add(function) value := &eval.Label{ Typ: types.AnyPointer, diff --git a/src/core/Function.go b/src/core/Function.go index 32de2cf..e38cbc7 100644 --- a/src/core/Function.go +++ b/src/core/Function.go @@ -4,6 +4,7 @@ import ( "git.urbach.dev/cli/q/src/dll" "git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/register" + "git.urbach.dev/cli/q/src/set" "git.urbach.dev/cli/q/src/token" ) @@ -18,7 +19,7 @@ type Function struct { Body token.List Input []*Parameter Output []*Parameter - Dependencies []*Function + Dependencies set.Ordered[*Function] DLLs dll.List Err error deferred []func() diff --git a/src/readme.md b/src/readme.md index 63ab66d..83641ce 100644 --- a/src/readme.md +++ b/src/readme.md @@ -24,6 +24,7 @@ - [riscv](riscv) - RISCV implementation (w.i.p.) - [scanner](scanner) - Scanner frontend used by `build` - [scope](scope) - Defines a `Scope` used for code blocks +- [set](set) - Generic set implementation - [sizeof](sizeof) - Calculates the byte size of numbers - [token](token) - Converts a file to tokens with the `Tokenize` function - [types](types) - Type system diff --git a/src/set/Ordered.go b/src/set/Ordered.go new file mode 100644 index 0000000..bc7caa5 --- /dev/null +++ b/src/set/Ordered.go @@ -0,0 +1,33 @@ +package set + +import ( + "iter" + "slices" +) + +// Ordered is an ordered set. +type Ordered[T comparable] struct { + values []T +} + +// Add adds a value to the set if it doesn't exist yet. +// It returns `false` if it already exists, `true` if it was added. +func (set *Ordered[T]) Add(value T) bool { + if slices.Contains(set.values, value) { + return false + } + + set.values = append(set.values, value) + return true +} + +// All returns an iterator over all the values in the set. +func (set *Ordered[T]) All() iter.Seq[T] { + return func(yield func(T) bool) { + for _, value := range set.values { + if !yield(value) { + return + } + } + } +}