#lang planet zwizwa/staapl/pic18 \ -*- forth -*- provide-all staapl pic18/double-math staapl pic18/double-pred staapl pic18/double-dict staapl pic18/execute \ A direct threaded Forth using native code primitives. NEXT is \ procedure return to an explicit interpreter loop. : _IP! fh ! fl ! ; : _exit r> fh ! r> fl ! ; : _dolit @f+ @f+ ; : _jump @f+ fl ! @f+ fh ! ; : _0jump or z? if drop _jump ; then drop @f+ drop @f+ drop ; : enter fl @ >r fh @ >r TOSL fl @! \ TOS cannot be movff dst, but src is ok TOSH fh @! pop ; : continue begin @f+ @f+ execute/b again : _bye _exit \ remove DTC continuation pop ; \ break the "continue" loop \ Bootstrap compiler words. macro : compile address ,, ; : literal >m ' _dolit compile m> ,, ; : _; ' _exit compile ; forth \ On-target compiler words. macro : >xt address lohi ; forth : _compile _, ; : _literal ' _dolit >xt _, _, ; \ Trampoline entry from native code. The 'interpret' word will run a \ dtc primitive or primitive wrapped program. : bye>r enter ' _bye compile ; : interpret \ ( lo hi -- ) bye>r \ install continuation into dtc code "bye ;" execute/b \ invoke the primitive (might be enter = wrapped program) continue ; \ invoke threaded continuation \ Return stack : _>r >r >r ; : _r> r> r> ; : _rdrop rdrop rdrop ; : _r rl rh ; \ Immediate words : _0 0 dup ; : _0jump, ' _0jump >xt _, ; : _jump, ' _jump >xt _, ; : _hole, _here@ _0 _, ; : _begin _here@ ; : _again _jump, _, ; : _until _0jump, _, ; : _if _0jump, _hole, ; : _then _>r _here@ _r> _cbuf _! ; : _else _>r _jump, _r> _hole, ; \ Dictionary meta data. \ For now we compile the dictionary meta data inline with the code so \ we can reuse compilation primitives. Later the dictionary could be \ separated. \ Compile a pstring to the dictionary. : compile-name \ lo hi -- _dup _@ drop \ lo hi nb.bytes >> 1+ \ nb.words for _dup _@ _, _cell+ next _drop ; \ Create a new dictionary entry. Format: [ next XT CT name code ] : word \ lo hi -- _here@ _>r \ Save location of new head pointer. _head _@ _, \ Compile link to old head. _r> _head _! \ Store new head pointer. _here@ _>r _0 _, \ Save XT hole + Compile stub. ' _compile >xt _, \ Compile CT compile-name \ Compile the name string. _here@ _r> _cbuf _! \ Patch XT hole. ; \ String comparison. Since one of them is in RAM and the other in \ FLASH both pointers can be used to iterate over the strings. : flash/ram-compare \ FH FL AH AL -- ? a!! f!! a/f-compare ; @a @f+ = if @a+ n-a/f-compare ; then 0 ; \ size needs to be equal : n-a/f-compare \ len -- 1 - c? if drop -1 ; then \ size = 0 => they are equal @a+ @f+ = if n-a/f-compare ; then \ recurse if character matches drop 0 ; \ untested \ Lookup a pstring in the flash dictionary. Returns 0 if not found, \ or a link to the dictionary record if found. : find \ lo hi -- _>r _last _@ : find-loop _dup or 0 = if _drop _rdrop _0 ; then \ Stop if it's zero _dup _r _@ flash/ram-compare if _rdrop ; then \ Compare and exit if found _@ find-loop ; \ Deref and continue. : init-dtc #x1000 lohi _here ! _0 _last ! ;