@@ -78,6 +78,7 @@ module Savi
7878 option " -b" , " --backtrace" , desc: " Show backtrace on error" , type: Bool , default: false
7979 option " -r" , " --release" , desc: " Compile in release mode" , type: Bool , default: false
8080 option " --fix" , desc: " Auto-fix compile errors where possible" , type: Bool , default: false
81+ option " --watch" , desc: " Run continuously, watching for file changes (EXPERIMENTAL)" , type: Bool , default: false
8182 option " --no-debug" , desc: " Compile without debug info" , type: Bool , default: false
8283 option " --llvm-ir" , desc: " Write generated LLVM IR to a file" , type: Bool , default: false
8384 option " --llvm-keep-fns" , desc: " Don't allow LLVM to remove functions from the output" , type: Bool , default: false
@@ -96,7 +97,11 @@ module Savi
9697 options.target_pass = Savi ::Compiler .pass_symbol(opts.pass) if opts.pass
9798 options.manifest_name = args.name.not_nil! if args.name
9899 Dir .cd(opts.cd.not_nil!) if opts.cd
99- Cli .run options, opts.backtrace
100+ if opts.watch
101+ Cli .run_with_watch(options, opts.backtrace)
102+ else
103+ Cli .run(options, opts.backtrace)
104+ end
100105 end
101106 end
102107 sub " build" do
@@ -302,6 +307,30 @@ module Savi
302307 end
303308 end
304309
310+ # This feature is experimental - it's currently not quite working,
311+ # due to some issues with inaccurate or incomplete caching of passes.
312+ # Also, it doesn't watch precisely the right set of files -
313+ # ideally it would watch all of the package globs that are in use,
314+ # as well as the manifest files where those packages are defined.
315+ # Once we get those issues ironed out, we should mark it as being
316+ # no longer experimental, and publicize it as a recommended way of working.
317+ def self.run_with_watch (options, backtrace = false )
318+ ctx = Savi .compiler.compile(Dir .current, options.target_pass || :run , options)
319+ finish_with_errors(ctx.errors, backtrace) if ctx.errors.any?
320+ last_compiled_at = Time .utc
321+
322+ FSWatch .watch(" ." , latency: 0.25 , recursive: true ) do |event |
323+ next unless event.created? || event.updated? || event.removed? || event.renamed?
324+ next if event.timestamp < last_compiled_at
325+
326+ ctx = Savi .compiler.compile(Dir .current, options.target_pass || :run , options)
327+ finish_with_errors(ctx.errors, backtrace) if ctx.errors.any?
328+ last_compiled_at = Time .utc
329+ end
330+
331+ sleep
332+ end
333+
305334 def self.eval (code, options, backtrace = false )
306335 _add_backtrace backtrace do
307336 dirname = " /tmp/savi-eval-#{ Random ::Secure .hex} "
0 commit comments