// logosz.s	
//
//  Compile the string on top of the data stack: (replace it with code)
//
// Dictionary formats:  (in file: dict2.s)
//
//	dict1_start:	dict2_start:	dict_start:
//	1 (special)	2 (special)	variable (normal)
//	------------	------------	------------
//	ascii=code(1)	ascii (2 bytes)	next_pointer (2 bytes)
//	priority (1)	priority (1)	Asciiz (variable + "0")
//	 		code (1)	priority (1 byte)
//					code (1 byte)
//  Register usage::
//
//	r15				// Program counter
//	r14				// link poiter
//	r13				// C-Sack (priority table)
//	r12 Top of Priority stack	// configuration base	OK
//	r11 Source Pointer		// byte-code pointer	Dest. Priority
//	r10 Dictonary pointer		// jump-table base	Dest. Code byt
//	r9  Destination Code		// spare		Dictionary ptr
//	r8  Priority			// spare		Source pointer
//	r7  Destination pointer		// D-Stack		OK
//	r6    (cued to source string, or to it's loccation in memory?)
//	r5  word length		    // variable-word length
//	r4  byte_2 (from dict.)	    // variable-word pointer
//	r3  byte_2 source	    // v-w next-word pointer
//	r2  byte_1 (from dict.)
//	r1  byte_1 source
//	r0  scratch byte
//
//----------------------------------------------------------------
//
// Setup:
//
clogos:
	push {r10,r11,r12,lr}	// save some registers
	mov r12,#0x40	// mark the bottom of the priority stack
	//
	mov r0,#0
	strb r0,[r7]	// zero-terminate the string (for blank CUE)
	mov r7,r6	// Cue R7 ptr. to Destination
	mov r11,r6	// Cue R11 ptr. to Source (both string start)

// ---------------------------------------------------------------
//
// Cue source past spaces and other blanks (00h-20h) to Next Word
//
CueLp:
	ldrb r1,[r11],+1	// load from Source [r11] and inc
	//
	// we're done if we get to the zero-terminator)
	//
	ands r0,r1,r1	//test r1 for == zero beq finish
	beq LogosDo
	//
	// Loop past all non-printing characters (0x0 - 0x20)
	//
	cmp r1,#0x21
	blt CueLp	// loop until >= 0x21

    //
    // Check for a single leading "Normalal" or "Special" Character:
    //
	//   !"#$%&'()*+,-./		21h (!) - 40h (@) special
	//  0123456789:;<=>?		41h (A) - 5Ah (Z) normal
	//  @ABC .. XYZ[\]^_		5Bh ([) - 60h (`) special
	//  `abc .. xyz{|}~ ..		61h (a) - 7Ah (z) normal
	//				7Bh ({) - FFh     special
	//
	// if character == special then goto number
	// if character == special then GOTO special
	// else: spec<41h,norm<5Bh,spec<61h,norm<7Bh,spec
	//
	cmp r1,#0x22	// double quote
	beq strcmp
	cmp r1,#0x27	// single quote
	beq strcmp
	cmp r1,#0x30
	blt special
	cmp r1,#0x39
	ble number
	cmp r1,#0x41
	blt special
	cmp r1,#0x5B
	blt normal
	cmp r1,#0x61
	blt special
	cmp r1,#0x7B
	bge special
	// else Normal (drop through)
//
// Evaluate Normal words (no special characters, except final "$")
//
normal:
//
// Evaluate each Letter and Append Next (until end of word)
//
	mov r5,r11	// mark starting point (for r5 length) in r11
	subs r5,#1	// but cue back 1 (we've passed byte #1 above)
	//		// and use r11 to scan string (and cue to end)
Loop2:	// get next character (from source string) in r1
	ldrb r1,[r11],+1   // this cues r11 past the end of the word
	// if character == $ then add and done
	cmp r1,#0x24
	beq keepend
	// if character == special then done
	cmp r1,#0x41
	blt dropend
	cmp r1,#0x5A		// scan string, looking for
	ble loop2		// any type of terminator
	cmp r1,#0x7A
	bgt dropend
	cmp r1,#0x61
	blt dropend
	b Loop2		// loop back to fetch next char.
dropend: sub r11,#1	// drop treminator end (cue r11 back)
keepend:		// just save final "$"  end
// ---------------------------------------------------------------------
// Word with normal characters found:
// Look up that word in the variable-length dictionary
//
lookup:
	mov r10,dict_start	// Cue r0 (r10?) to Dictionary Start
	//			// r5 is word start and r11 is word end
clulp1:	subs r0,r11,r5	// set (or reset) r0 to loop count (end-start)
	ldrh r3,[r10],+2 // load next-pointer into r3
	//		 (r11 points to the word's start-pointer)
	mov r4,r5	// cue r4 to (or back to) the beginning of the word
	//
clulp2:	ldrb r1,[r4],+1	 // read a letter from word, cue to next
	ldrb r2,[r10],+1 // read a letter from dictionary, next
	//
	cmp r1,r2	//  if they match ...
	beq nxtltr	//  Then go check next letter
	//		//  (else drop thru to check next word)
nxtwrd:	mov r10,r3	// else, cue dict. to (r3 saved) next word
	ands r10,r10	// is another word avaiilable?
	bne clulp1	// (if no zero terminator) then test it too
	beq notfound1	// else (0 terminator) report "not-found" error
	//
nxtltr:	subs r0,#1	// length-1, zero letters remaining?
	bne clulp2	// if length not==0, then check the next letter
	//
	ldrb r2,[r10],+1 // make sure we'ree at end of asciiZ dict word
	cmp r0,r2	// (both count and final ASCIIZ "Zero" match)
	bne nxtwrd	// else try the next word
	//
	ldrb r8,[r10],+1 // if ==0, then fetch priority (r8)
	ldrb r9,[r10]	// and code (r9)
	b found2	// goto compile code

// ---------------------------------------------------------------------
// number found
//
number:	// immediate-compile number (first, or only, digit in r1)
	ldrb r0,[r11]		// fetch next digit (or terminator)
	cmp r0,#0x30
	blt numbr1
	cmp r0,#0x39
	ble numbr2
//
//  If terminator: then single digit only, so:
//
numbr1:	strb r1,[r7],+1	// compile that digit
	b CueLp		// then go get the next chatacter
//
//  Else: make a word out of the digits
//
numbr2:	subs r1,#0x30	// ascii to binary 0-9 (acumulator in R1)
	//  Then collect the other digits:
nmbrlp:	ldrb r2,[r11]	// candidate digit or terminator in r2
	cmp r2,#0x30
	blt nmbrnd
	cmp r2,#0x39	//end if terminator
	bgt nmbrnd
	// else cue to next digit
	add r11,#1
	// and add digit to accumulator:
	subs r2,#0x30	// ascii to binary
	// accumulator * 10
	add r1,r1,r1	// double old number
	add r1,r1,r1,lsl #2	// then x5 (for x10)
	// and add new digit:
	add r1,r1,r2
	b nmbrlp

	// Number collected, compile by size:
nmbrnd:	mov r0,#256
	cmp r1,r0	// ' byte?
	bge ntbyte
	//
	mov r0,0x27	// Bytes compile with "'" symbol
	strb r0,[R7],+1
	strb r1,[R7],+1		//+byte
	b CueLp		// go get next character

ntbyte:	lsls r0,#8	// # hword?
	cmp r0,r1
	bge nthwrd
	//
	mov r0,0x23	// halfwords compile "#" symbol
	strb r0,[R7],+1
	strh r1,[R7],+2		//+halfword
	b CueLp		// go get next character

nthwrd:	mov r0,0xa3	// words compile 0x80+"#" symbol
	strb r0,[R7],+1
	str r1,[R7],+4		//+word
	b CueLp		// go get next character

// ----------------------------------------------------------------
//
//	Compile a string (terminator in r1)
//
strcmp:	mov r0,#0x24	// #0x24 start string with a "$"
	strb r0,[r7],+1	// compile it
	//
strclp:	ldrb r0,[r11],+1
	cmp r0,r1	// terminator
	beq strcnd
	strb r0,[r7],+1
	b strclp
	//
strcnd:	mov r0,#0	//#0 terminate
	strb r0,[r7],+1	// compile it
	b CueLp

	//
	// xfer the entire string
	//
//strcpl:	ldrb r0,[r11],+1  // get next character
//	cmp r0,r1	// does it terminate the string?
//	beq strcnd	// end if it does
//	//
//	strb r0,[r7],+1	// else compile the character
//	b strcpl	// and get the next character
	//
	// Terminate the string
	//
//strcnd:
//	b Cuelp		// go get next character

//-----------------------------------------------------------------

// Special-character found
//
special:
	// cue for a 2-character combination:
	//
	mov r10,dict2_start	// cue r10 to "dict2"
	//ldrb r1,[r11],+1	// 1st byte from source loaded above
	ldrb r3,[r11],+1	// load 2nd byte from source
	//
d2loop:	// fetch dictionary entry (check for last entry)
	ldrb r2,[r10],+1	// get 1st character
	ands r0,r2,r2		// end of dict2 table?
	beq special1		//  goto special1 if so
	ldrb r4,[r10],+1	// get 2nd character
	ldrb r9,[r10],+1	// get dest. character
	ldrb r8,[r10],+1	// get priority byte
	//
	cmp r1,r2
	bne d2loop		// loop until
	cmp r3,r4		// both characters match
	bne d2loop
	beq found2		//
//
// but if not found ...
// then look in 1-special-character dictionary:
//
special1: /// cue for 1-character:
	mov r10,dict1_start	/// cue r10 to "dict1"
	// (r10 is already cued to "dict1"
	sub r11,#1	// drop 2nd byte from source ptr
	mov r9,r1	// and r1 is source(r1) & dest.(r9) character
	//
d1loop:	ldrb r2,[r10],+1  // get the dict character and incriment
	ands r0,r2,r2	  // end of dict2 table?
	beq notfound2
	ldrb r8,[r10],+1  // get priority byte and incriment
	cmp r1,r2	  // match to dictionary?
	bne d1loop
//	// (beq found1)
//
// Normal or Special character match found, so compile it:
//
//found1:	//
	// compile (,)
	//  9priority adjustments for "(" "," and ")"0
	//
	cmp r8,0x3f	// is priority for ( , ) ??
	bne found2	// else goto normal compile
	//
	cmp r9,0x28	// "(" ?
	beq cskip3	// just push r9 "(" and r12 (0x3f)
	//		// (same as an immediate function)
	// Not 0x28, so ", or ) so:
	//   compile back to ")" (>=0x40 is an error)
cplp:	cmp r12,0x3f
	beq cpldn1
	//
	pop {r0}	// else, get previous function from c-stack
	strb r0,[r7],+1	// and compile it now
	pop {r12}	// pop next c-stack priority
	b cplp		// and loop back until "("
	//
cpldn1:	cmp r1,0x2c	// is it a ","?
	beq CueLp	// if so, then just leave the "(" there
	//
	pop {r0}	// else, drop "(" from c-stack
	pop {r12}	// and pop next c-stack priority
	b CueLp		// done
	//
	// normal compile loop
	//   normal priority adjustments
	//
found2:	cmp r8,0x31	// 1: always compile immediate numbers
	bne cskip1
	strb r9,[r7],+1
	b cskpnd
	//
cskip1: cmp r8,0x32	// 2: always push immediate functions
	beq cskip3
	//		// Else:
cloop2: cmp r8,r12	// compare target priority with C-stack "Top"
	blt cskip3	// when done, goto "push new" (to use later)
	pop {r0}	// else, get previous function from c-stack
	strb r0,[r7],+1	// and compile it now
	pop {r12}	// pop next c-stack priority
	b cloop2	// and loop
	//
	//		// Finally:
cskip3:	push {r12}	// push previous status onto c-stack
	push {r9}	// push present function code onto c-stack
	mov r12,r8	// & present priority status goes on "Top"
cskpnd:	//
	// done with this word, so go get the next one
	//
	b CueLp

//
//  Final End of the String:
//
LogosDo:
//
//  So: Compile everything that's still left on the Data Stack:
//
cendlp:	cmp r12,#0x40	// compare target priority with C-stack "Top"
	beq cndxit	// We're done when we reach it
	pop {r9}	// else, drop previous function from c-stack
	strb r9,[r7],+1	//	 compile it now
	pop {r12}	//	 pop the next c-stack priority
	b cendlp	//	 and loop until we're done
cndxit:
	mov r9,#0       // terminate string with final zero
	strb r9,[r7],+1	// compile that zero
	//
	// Finally, End and chain to next operation
	//   Leaves r6 at start of string
	//   r7 is now cued to just past end of string
	//
	pop {r10,r11,r12,lr}	// restore the saved registers
	ldrb r0,[r11],#1        // and chain
	ldr r15,[r10,r0,lsl #2]

//-----------------------------------------------------------------
//
//  Report Error
//
notfound1:
	mov r9,0xc7	// "<?>"
	strb r9,[r7],+1
	b cendlp
notfound2:
	mov r9,#0x3a	// ":"
	strb r9,[r7],+1
	mov r9,r1	// offending SRC character
	strb r9,[r7],+1
	mov r9,0xc7	// "<?>"
	strb r9,[r7],+1
	b cendlp

//-----------------------------------------------------------------
//dict2_start: // 2 valid characters,character code,priority,zero termination
// (To turn priority 0-15 into ascii: use "0123456789:;<=>?" 0x30-0x3f)
//<=L,>=G,===,!=N,:=:,=:#,+=X,-=X,*=X,/=X,%=X,<<X,>>X,++X,=$K,+$J@$Q,:$S,=$K,0x00
//.asciz"<=L6>=G6===7!=N7=::>:=#>+=X>-=X>*=X?/=X>%=X><<X>>>X>++X>=$K>+$J>@$Q>:$S>=$K>"
//dict1_start: // valid single-character list, priority, zero tremination
//.asciz"@2+4-4*3/3%301112131415161718191&8|:^9!2~2<6>6(?)?,??>"
//		// link pointer
//dict_start:	// "source_text" (asciiZ)
//		// priority, "bytecode"
//name_false:	.hword name_true
//		.asciz "F"
//		.byte 1,0x30	//"0"
//name_true:	.hword name_abs	//name_and
//		.asciz "T"
//		.byte 1,0x54	//"T"
//name_abs:	.hword name_n	//name_shl
//		.asciz "abs"
//		.byte 2,0x41	//"A"
//name_n:		.hword name_do
//		.asciz "n"
//		.byte 0,0x6e	//"n"
//name_do:	.hword name_until
//		.asciz "do"
//		.byte 0,0x5b	//"["
//name_until:	.hword name_if
//		.asciz "until"
//		.byte 16,0x5d	//"]"
//name_if:	.hword name_then
//		.asciz "if"
//		.byte 0x80,0x96	//undefined
//name_then:	.hword name_else
//		.asciz "then"
//		.byte 0x81,0x97
//name_else:	.hword name_endif
//		.asciz "else"
//		.byte 0x82,0x5C	// 5C: "\"
//name_endif:	.hword name_for
//		.asciz "endif"
//		.byte 0x83,0x5D		// "endif",0,0x83,"]"
//name_for:	.hword name_to
//		.asciz "for"
//		.byte 16,0x98		//;undefined
//name_to:	.hword name_next
//		.asciz "to"
//		.byte 16,0x99		//;undefined
//name_next:	.hword name_rnd
//		.asciz "next"
//		.byte 16,0x9a		//;undefined
//name_rnd:	.hword name_sq
//		.asciz "rnd"
//		.byte 0,0x72	//"r"
//name_sq:	.hword name_sqr
//		.asciz "sq"
//		.byte 2,0x58	//"X"
//name_sqr:	.hword name_crlf
//		.asciz "sqr"
//		.byte 2,0x73	//"s"
//name_crlf:	.hword name_print
//		.asciz "crlf"
//		.byte 6,0x0a
//name_print:	.hword name_print2
//		.asciz "print"
//		.byte 14,0x3f	//"?"
//name_print2:	.hword name_byte
//		.asciz "?"
//		.byte 14,0x3f	//"?"
//name_byte:	.hword name_half
//		.asciz "byte"
//		.byte 14,0x42	//"B"
//name_half:	.hword name_word
//		.asciz "half"
//		.byte 14,0x48	//"H"
//name_word:	.hword name_char
//		.asciz "word"
//		.byte 14,0x57	//"W"
//name_char:	.hword name_input	//;single character output
//		.asciz "char"
//		.byte 14,0x63	//"C"
//name_input:	.hword name_key
//		.asciz "input"		// undefined?
//		.byte 0,0x9b
//name_key:	.hword name_prints
//		.asciz "key"
//		.byte 0,0x6b	//"k"
//name_prints:	.hword name_inputs
//		.asciz "print$"
//		.byte 14,0x6f	//"O"
//name_inputs:	.hword name_left$	//name_loads
//		.asciz "input$"
//		.byte 0,0x49	//"I"		// 0??
//name_lefts:	.hword name_rights
//		.asciz "left$"
//		.byte 2,0x50	//"P"
//name_rights:	.hword name_join
//		.asciz "rigt$"
//		.byte 2,0x52	//"R"
//name_join:	.hword name_length
//		.asciz "+$"
//		.byte 4,0x4a	//"J"
//name_length:	.hword name_drop
//		.asciz "length"
//		.byte 2,0x4d	//"M"	//#;measure
//name_drop:	.hword name_chrs
//		.asciz "drop$"
//		.byte 14,0x7f	//"-"
//name_chrs:	.hword name_main
//		.asciz "chr$"
//		.byte 2,0x40	//"@"	//#;undefined
//name_main:	.hword name_end
//		.asciz "main"
//		.byte 0x89,0x9c
//name_end:	.hword 0
//		.asciz ":End""
//		.byte 14,0x3f	//"?"

