global var
CH
CP
CS   

isNum c
  (c >= 48) & (c <= 57)

isSpace c
  (c == 32) | (c == 10) | (c < 0)

readc { c }
  c = getchar()
//  printc c
  CH = c
  ret c

readi c { n pos }
  n = c - 48
  pos = n
  while ! isSpace readc
    n = n*10 + CH - 48
  if pos != 0 
    ret n
  else
    ret 0-n

// it reads input and write it to screen
boot {op arg i}
  op = readi readc
  while op != 0
    arg = readi readc
//    CS[i] = (arg << 8) | op
    print op printc 32 
    print arg printc 10
//    i++
    op = readi readc

// this is the first image
// it can read s-object stream

// we test it by appending some s-object
// at the end of the first image
// and "boot" will read it then write it
// out to the screen.
// for example:
32 17
23 0
38 1
0

// for the s-code and executable files 
// of this first image
// see "boot1-s.txt" "boot1.obj"

// after the basic functions are working
// now we write boot2 to be used to load
// subsequent functions
// i is set to the appropriate address
// (after boot2)

boot2 {op arg i}
  CS = 0
  i = 130
  op = readi readc
  while op != 0
    arg = readi readc
    CS[i] = (arg << 8) | op
    i++
    op = readi readc

// the second stage is to write
// a scanner that can read symbols
// and store them in a symbol table
// the scanner is called "lexical analyser"

// this is the symbol table
// ??? explain trie symbol table

freecell = 0	// pointer to free sym
sym = 2000	// symbol table, array 1000
tkval = 0       // value of current token

// a cell has 4 fields: char,right,next,atr
newcell c { k }
  k = freecell
  freecell = freecell + 4
  sym[k] = c
  ret k

search i c 	// if sym[i]=0 insert c at i
  if sym[i] == 0
    sym[i] = newcell c
  ret sym[i]

// return index to symtab, 0 if EOF, 1 if num
lex { i }
  while isSpace readc
    if CH < 0 break  // skip blank stop at EOF
  if isNum CH
    tkval = readi CH
    ret 1	     // it is a number
  i = 0
  while ! isSpace CH	// check sep, EOF
    i = search i+2 CH	// next of i
    while sym[i] != CH	// match right
      i = search i+1 CH // right of i
    CH = readc		// read next
  ret i

// we test lex by appending some symbols
// at the end and read them until found 0

testlex { i }
  sym = array 100
  i = lex
  while tkval != 0
    print i printc 32
    i = lex

// now we use "boot2" to read these codes
// into code segment and call testlex

// example of input to testlex
1 2 aa bb x 
0

// now is the final stage
//
// lex starts working
// we build symbol table by reading 
// "associative pair" symbol-value 
// into the table

initsym { i j }
  freecell = 4
  sym = array 1000
  i = lex             // read sym
  while i > 1
    j = lex	      // read value
    sym[i+3] = tkval  // set value
    i = lex	      // read sym

// with a symbol table 
// we can write an assembler

outc op arg
  CS[CP] = (arg << 8) | op
  CP = CP + 1

asm { i j op }	     // a tiny assembler
  i = lex
  while i > 1
    op = sym[i+3]
    tkval = 0
    if op > 23 j = lex
    outc op tkval
    i = lex

main
  initsym
  CS = 301000
  CP = 99
  asm
  print fac 6
  