aboutsummaryrefslogtreecommitdiffstats
path: root/copilot.moon
blob: 8b3602a3871ad1e36effbcfa75848442ce46b764 (plain)
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
lfs = require 'lfs'
import parse, globals, Scope, Registry from require 'core'

slurp = (file) ->
  file = io.open file, 'r'
  with file\read '*all'
    file\close!

spit = (file, str) ->
  file = io.open file, 'w'
  file\write str
  file\close!

class Copilot
  new: (@file) =>
    @registry = Registry!

    @last_modification = 0

    mode = lfs.attributes @file, 'mode'
    if mode != 'file'
      error "not a file: #{@file}"

  patch: =>
    ast = L\try "error parsing:", parse, slurp @file
    if not ast
      L\error "error parsing"
      return

    scope = Scope globals
    root = L\try "error evaluating:", ast\eval, scope, @registry
    return unless root

    @root = root if root
    ast

  tick: =>
    @poll!

    if @root
      L\try "error evaluating:", @registry\wrap_tick ->
        @root\tick_io!
        @root\tick!

  tb = (msg) -> debug.traceback msg, 2
  poll: =>
    { :mode, :modification } = (lfs.attributes @file) or {}
    if mode != 'file'
      return

    if @last_modification < modification
      L\log "#{@file} changed at #{modification}"
      ast = L\push @registry\wrap_eval @\patch
      spit @file, ast\stringify! if ast
      @last_modification = os.time!

:Copilot