convert :: File -> Either Error [Register]
convert f = mapM compile f where
  compile (_, s, Code l) = (make s . encode) <$> mapM instruct l
  compile (_, s, Data t) = Right $ make s t
  make Nothing t = R (size t) t
  make (Just s) t = R s (trim s t)
  instruct (NILIFY tgt)           = Nilify      <$> r tgt
  instruct (CONS fnt bck tgt)     = Construct   <$> r fnt   <*> r bck <*> r tgt
  instruct (DEST src fnt bck)     = Deconstruct <$> r src   <*> r fnt <*> r bck
  instruct (COPY src dst)         = CopyIfNil   <$> r "NIL" <*> r src <*> r dst
  instruct (CONDCOPY tst src dst) = CopyIfNil   <$> r tst   <*> r src <*> r dst
  instruct (EXEC prg)             = CopyIfNil   <$> r "NIL" <*> r prg <*> return 0
  instruct (CONDEXEC tst prg)     = CopyIfNil   <$> r tst   <*> r prg <*> return 0
  instruct (PUSH src stk)         = Construct   <$> r src   <*> r stk <*> r stk
  instruct (POP stk tgt)          = Deconstruct <$> r stk   <*> r tgt <*> r stk
  instruct (WRITE src)            = CopyIfNil   <$> r "NIL" <*> r src <*> return 2
  instruct (CONDWRITE tst src)    = CopyIfNil   <$> r tst   <*> r src <*> return 2
  r x = maybe (Left $ NoSuchRegister x) Right (elemIndex x $ names f)
convert :: File -> Either Error [Register]
convert f = mapM compile f where
  compile (_, s, Code l) = (make s . encode) <$> mapM instruct l
  compile (_, s, Data t) = Right $ make s t
  make Nothing t = R (size t) t
  make (Just s) t = R s (trim s t)
  instruct (NILIFY tgt)           = Nilify      <$> r tgt
  instruct (CONS fnt bck tgt)     = Construct   <$> r fnt   <*> r bck <*> r tgt
  instruct (DEST src fnt bck)     = Deconstruct <$> r src   <*> r fnt <*> r bck
  instruct (COPY src dst)         = CopyIfNil   <$> r "NIL" <*> r src <*> r dst
  instruct (CONDCOPY tst src dst) = CopyIfNil   <$> r tst   <*> r src <*> r dst
  instruct (EXEC prg)             = CopyIfNil   <$> r "NIL" <*> r prg <*> return 0
  instruct (CONDEXEC tst prg)     = CopyIfNil   <$> r tst   <*> r prg <*> return 0
  instruct (PUSH src stk)         = Construct   <$> r src   <*> r stk <*> r stk
  instruct (POP stk tgt)          = Deconstruct <$> r stk   <*> r tgt <*> r stk
  instruct (WRITE src)            = CopyIfNil   <$> r "NIL" <*> r src <*> return 2
  instruct (CONDWRITE tst src)    = CopyIfNil   <$> r tst   <*> r src <*> return 2
  r x = maybe (Left $ NoSuchRegister x) Right (elemIndex x $ names f)
convert f = mapM compile f where
  compile (_, s, Code l) = (make s . encode) <$> mapM instruct l
  compile (_, s, Data t) = Right $ make s t
  make Nothing t = R (size t) t
  make (Just s) t = R s (trim s t)
  instruct (NILIFY tgt)           = Nilify      <$> r tgt
  instruct (CONS fnt bck tgt)     = Construct   <$> r fnt   <*> r bck <*> r tgt
  instruct (DEST src fnt bck)     = Deconstruct <$> r src   <*> r fnt <*> r bck
  instruct (COPY src dst)         = CopyIfNil   <$> r "NIL" <*> r src <*> r dst
  instruct (CONDCOPY tst src dst) = CopyIfNil   <$> r tst   <*> r src <*> r dst
  instruct (EXEC prg)             = CopyIfNil   <$> r "NIL" <*> r prg <*> return 0
  instruct (CONDEXEC tst prg)     = CopyIfNil   <$> r tst   <*> r prg <*> return 0
  instruct (PUSH src stk)         = Construct   <$> r src   <*> r stk <*> r stk
  instruct (POP stk tgt)          = Deconstruct <$> r stk   <*> r tgt <*> r stk
  instruct (WRITE src)            = CopyIfNil   <$> r "NIL" <*> r src <*> return 2
  instruct (CONDWRITE tst src)    = CopyIfNil   <$> r tst   <*> r src <*> return 2
  r x = maybe (Left $ NoSuchRegister x) Right (elemIndex x $ names f)