-
Notifications
You must be signed in to change notification settings - Fork 10
/
run.go
82 lines (63 loc) · 1.34 KB
/
run.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
package run
import (
"fmt"
"os"
"sync"
"github.com/cloe-lang/cloe/src/lib/compile"
"github.com/cloe-lang/cloe/src/lib/core"
"github.com/cloe-lang/cloe/src/lib/systemt"
)
const maxConcurrentEffects = 256
var sem = make(chan bool, maxConcurrentEffects)
// Run runs effects.
func Run(os []compile.Effect) {
go systemt.RunDaemons()
wg := sync.WaitGroup{}
for _, v := range os {
wg.Add(1)
if v.Expanded() {
go evalEffectList(v.Value(), &wg, fail)
} else {
sem <- true
go runEffect(v.Value(), &wg, fail)
}
}
wg.Wait()
}
func evalEffectList(v core.Value, parent *sync.WaitGroup, fail func(error)) {
wg := sync.WaitGroup{}
defer func() {
wg.Wait()
parent.Done()
}()
for {
if b, err := core.EvalBoolean(core.EvalPure(core.PApp(core.Equal, v, core.EmptyList))); err != nil {
fail(err.(*core.ErrorType))
} else if b {
break
}
wg.Add(1)
sem <- true
go runEffect(core.PApp(core.First, v), &wg, fail)
v = core.PApp(core.Rest, v)
}
}
func runEffect(v core.Value, wg *sync.WaitGroup, fail func(error)) {
defer func() {
<-sem
wg.Done()
}()
if err, ok := core.EvalImpure(v).(*core.ErrorType); ok {
fail(err)
}
}
var fail = failWithExit(os.Exit)
func failWithExit(exit func(int)) func(error) {
return func(err error) {
_, err = fmt.Fprint(os.Stderr, err)
if err != nil {
panic(err)
}
exit(1)
}
}