import "io"

let enable_ints(v) be
{ assembly
  { load  r1, [<v>]
    setsr r1, $intvec      // set special register
    load  r1, 0
    setfl r1, $ip          // set flag "interrupt being processed"
} }

let set_timer(t) be
{ assembly
  { load  r1, [<t>]
    setsr r1, $timer } }

let timer_handler() be
{ out("\n  Boo!\n");
  set_timer(50000000);
  ireturn }

let stop = false;          // ugly global variable, only used for this experiment

let keyboard_handler() be
{ let c, v = vec 3;
  assembly                 // see the "Advanced Hardware Operations" document,
  { load  r1, [<v>]        // pages 6 and 12 for this.
    load  r2, $terminc
    store r2, [r1+0]
    load  r2, 1
    store r2, [r1+1]
    load  r2, <c>
    store r2, [r1+2]
    peri  r2, r1 }
  out("you typed '%c' = %d\n", c, c);
  if c = 'X'-64 then stop := true;       // that's control-X
  ireturn }

let compute() be                 // all this does is compute slowly so that there
{ let x = 0;                     // is some ongoing task for the interrupts to
  for i = 0 to 1000 do           // interrupt. Please don't do this for real, use
  { out("%d\n", x);              // assembly { pause } in a small loop to idle
    if stop then break;          // instead
    for j = 1 to 500 do
    { if stop then break;
      for k = 0 to 1000 do
        x +:= 1;
      for k = 0 to 999 do
        x -:= 1 } }
  out("all done\n") }

manifest
{ iv_none = 0,        iv_memory = 1,      iv_pagefault = 2,   iv_unimpop = 3,
  iv_halt = 4,        iv_divzero = 5,     iv_unwrop = 6,      iv_timer = 7,
  iv_privop = 8,      iv_keybd = 9,       iv_badcall = 10,    iv_pagepriv = 11,
  iv_debug = 12,      iv_intrfault = 13 }

let start() be
{ let ivec = vec(20), n;

  for i = 0 to 19 do
    ivec ! i := nil;
  ivec ! iv_timer := timer_handler;
  ivec ! iv_keybd := keyboard_handler;
  
  enable_ints(ivec);
  set_timer(50000000);

  compute();

  out("What is your favourite number? ");
  n := inno();                              // this stops working of course.
  out("Yuck! %d is terrible\n", n); }