#lang scheme/base
(require (planet soegaard/galore:4/set))
(define-struct task (name dependencies action) #:prefab)
(define-syntax define-task
(syntax-rules ()
[(define-task name (dependency ...))
(define-task name (dependency ...) (void))]
[(define-task name (dependency ...) expr0 expr1 ...)
(begin
(define name
(make-task (quote name)
(list dependency ...)
(lambda () expr0 expr1 ...)))
(provide name))]))
(define (task-traverse task [visited (make-eq)] [order null])
(define children (task-dependencies task))
(for/fold ([visited (insert task visited)]
[order (cons task order)])
([t (in-list children)])
(if (member? t visited)
(values visited order)
(task-traverse t visited order))))
(define (task-run-action task)
((task-action task)))
(provide
(struct-out task)
define-task
task-traverse
task-run-action)