-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch.go
111 lines (90 loc) · 2.9 KB
/
patch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package synthdown
import (
"fmt"
"github.com/alecthomas/participle/v2/lexer"
)
// FirstPatchHasInputError is an error signifying that the
// patch starts with an input, which is a logical absurdity; if it
// has an input from _somewhere_ then it cannot be the start of a patch
// unless it plugs into its self, or is a snippet.
//
// Neither of which are supported, and wont be until we suddenly realise
// it should be
type FirstPatchHasInputError struct {
m Module
}
// Error satisifies the `error` interface, returning a message explaining
// where the errant initial input lives
func (e FirstPatchHasInputError) Error() string {
return fmt.Sprintf("the first module of the patch described at %s has an input", e.m.Pos)
}
// LastPatchHasOutputError is an error signifying that the
// patch starts with an output, which is a logical absurdity; if it
// has an output from _somewhere_ then it cannot be the start of a patch
// unless it plugs into its self, or is a snippet.
//
// Neither of which are supported, and wont be until we suddenly realise
// it should be
type LastPatchHasOutputError struct {
m Module
}
// Error satisifies the `error` interface, returning a message explaining
// where the errant initial output lives
func (e LastPatchHasOutputError) Error() string {
return fmt.Sprintf("the last module of the patch described at %s has an output", e.m.Pos)
}
// MissingInputError is raised where a module should have an input, but
// doesn't
type MissingInputError struct {
m Module
}
// Error returns an explanation of which module is missing an input jack
func (e MissingInputError) Error() string {
return fmt.Sprintf("missing input jack at %s", e.m.Pos)
}
// MissingOutputError is raised where a module should have an output, but
// doesn't
type MissingOutputError struct {
m Module
}
// Error returns an explanation of which module is missing an output jack
func (e MissingOutputError) Error() string {
return fmt.Sprintf("missing output jack at %s", e.m.Pos)
}
// Patch represents a set of modules cabled together from jack to jack
// which hopefully makes an interesting noise
type Patch struct {
Pos lexer.Position
Modules []Module `parser:"@@ ('-' '>' @@)*"`
}
// Validate runs through a patch and checks it against a set of rules
func (p Patch) Validate() (err error) {
modulesLen := len(p.Modules)
if modulesLen == 0 {
return
}
// Ensure first module _doesn't_ have an input
first := p.Modules[0]
if first.Input != nil {
return FirstPatchHasInputError{first}
}
// Ensure the last module _doesn't_ have an output
last := p.Modules[modulesLen-1]
if last.Output != nil {
return LastPatchHasOutputError{last}
}
if modulesLen <= 2 {
return
}
// Ensure every other module has an input and an output
for i := 1; i < modulesLen-1; i++ {
mod := p.Modules[i]
if mod.Input == nil {
return MissingInputError{mod}
}
if mod.Output == nil {
return MissingOutputError{mod}
}
}
return
}