Annotation of gforth/kernel/cond.fs, revision 1.1
1.1 ! anton 1: \ Structural Conditionals 12dec92py
! 2:
! 3: \ Copyright (C) 1995-1997 Free Software Foundation, Inc.
! 4:
! 5: \ This file is part of Gforth.
! 6:
! 7: \ Gforth is free software; you can redistribute it and/or
! 8: \ modify it under the terms of the GNU General Public License
! 9: \ as published by the Free Software Foundation; either version 2
! 10: \ of the License, or (at your option) any later version.
! 11:
! 12: \ This program is distributed in the hope that it will be useful,
! 13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
! 14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 15: \ GNU General Public License for more details.
! 16:
! 17: \ You should have received a copy of the GNU General Public License
! 18: \ along with this program; if not, write to the Free Software
! 19: \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 20:
! 21: here 0 , \ just a dummy, the real value of locals-list is patched into it in glocals.fs
! 22: AConstant locals-list \ acts like a variable that contains
! 23: \ a linear list of locals names
! 24:
! 25:
! 26: variable dead-code \ true if normal code at "here" would be dead
! 27: variable backedge-locals
! 28: \ contains the locals list that BEGIN will assume to be live on
! 29: \ the back edge if the BEGIN is unreachable from above. Set by
! 30: \ ASSUME-LIVE, reset by UNREACHABLE.
! 31:
! 32: : UNREACHABLE ( -- ) \ gforth
! 33: \ declares the current point of execution as unreachable
! 34: dead-code on
! 35: 0 backedge-locals ! ; immediate
! 36:
! 37: : ASSUME-LIVE ( orig -- orig ) \ gforth
! 38: \ used immediatly before a BEGIN that is not reachable from
! 39: \ above. causes the BEGIN to assume that the same locals are live
! 40: \ as at the orig point
! 41: dup orig?
! 42: 2 pick backedge-locals ! ; immediate
! 43:
! 44: \ Control Flow Stack
! 45: \ orig, etc. have the following structure:
! 46: \ type ( defstart, live-orig, dead-orig, dest, do-dest, scopestart) ( TOS )
! 47: \ address (of the branch or the instruction to be branched to) (second)
! 48: \ locals-list (valid at address) (third)
! 49:
! 50: \ types
! 51: 0 constant defstart
! 52: 1 constant live-orig
! 53: 2 constant dead-orig
! 54: 3 constant dest \ the loopback branch is always assumed live
! 55: 4 constant do-dest
! 56: 5 constant scopestart
! 57:
! 58: : def? ( n -- )
! 59: defstart <> abort" unstructured " ;
! 60:
! 61: : orig? ( n -- )
! 62: dup live-orig <> swap dead-orig <> and abort" expected orig " ;
! 63:
! 64: : dest? ( n -- )
! 65: dest <> abort" expected dest " ;
! 66:
! 67: : do-dest? ( n -- )
! 68: do-dest <> abort" expected do-dest " ;
! 69:
! 70: : scope? ( n -- )
! 71: scopestart <> abort" expected scope " ;
! 72:
! 73: : non-orig? ( n -- )
! 74: dest scopestart 1+ within 0= abort" expected dest, do-dest or scope" ;
! 75:
! 76: : cs-item? ( n -- )
! 77: live-orig scopestart 1+ within 0= abort" expected control flow stack item" ;
! 78:
! 79: 3 constant cs-item-size
! 80:
! 81: : CS-PICK ( ... u -- ... destu ) \ tools-ext
! 82: 1+ cs-item-size * 1- >r
! 83: r@ pick r@ pick r@ pick
! 84: rdrop
! 85: dup non-orig? ;
! 86:
! 87: : CS-ROLL ( destu/origu .. dest0/orig0 u -- .. dest0/orig0 destu/origu ) \ tools-ext
! 88: 1+ cs-item-size * 1- >r
! 89: r@ roll r@ roll r@ roll
! 90: rdrop
! 91: dup cs-item? ;
! 92:
! 93: : cs-push-part ( -- list addr )
! 94: locals-list @ here ;
! 95:
! 96: : cs-push-orig ( -- orig )
! 97: cs-push-part dead-code @
! 98: if
! 99: dead-orig
! 100: else
! 101: live-orig
! 102: then ;
! 103:
! 104: \ Structural Conditionals 12dec92py
! 105:
! 106: : ?struc ( flag -- ) abort" unstructured " ;
! 107: : sys? ( sys -- ) dup 0= ?struc ;
! 108: : >mark ( -- orig )
! 109: cs-push-orig 0 , ;
! 110: : >resolve ( addr -- ) here over - swap ! ;
! 111: : <resolve ( addr -- ) here - , ;
! 112:
! 113: : BUT
! 114: 1 cs-roll ; immediate restrict
! 115: : YET
! 116: 0 cs-pick ; immediate restrict
! 117:
! 118: \ Structural Conditionals 12dec92py
! 119:
! 120: : AHEAD ( compilation -- orig ; run-time -- ) \ tools-ext
! 121: POSTPONE branch >mark POSTPONE unreachable ; immediate restrict
! 122:
! 123: : IF ( compilation -- orig ; run-time f -- ) \ core
! 124: POSTPONE ?branch >mark ; immediate restrict
! 125:
! 126: : ?DUP-IF ( compilation -- orig ; run-time n -- n| ) \ gforth question-dupe-if
! 127: \G This is the preferred alternative to the idiom "?DUP IF", since it can be
! 128: \G better handled by tools like stack checkers. Besides, it's faster.
! 129: POSTPONE ?dup-?branch >mark ; immediate restrict
! 130:
! 131: : ?DUP-0=-IF ( compilation -- orig ; run-time n -- n| ) \ gforth question-dupe-zero-equals-if
! 132: POSTPONE ?dup-0=-?branch >mark ; immediate restrict
! 133:
! 134: Defer then-like ( orig -- )
! 135: : cs>addr ( orig/dest -- ) drop >resolve drop ;
! 136: ' cs>addr IS then-like
! 137:
! 138: : THEN ( compilation orig -- ; run-time -- ) \ core
! 139: dup orig? then-like ; immediate restrict
! 140:
! 141: ' THEN alias ENDIF ( compilation orig -- ; run-time -- ) \ gforth
! 142: immediate restrict
! 143: \ Same as "THEN". This is what you use if your program will be seen by
! 144: \ people who have not been brought up with Forth (or who have been
! 145: \ brought up with fig-Forth).
! 146:
! 147: : ELSE ( compilation orig1 -- orig2 ; run-time f -- ) \ core
! 148: POSTPONE ahead
! 149: 1 cs-roll
! 150: POSTPONE then ; immediate restrict
! 151:
! 152: Defer begin-like ( -- )
! 153: ' noop IS begin-like
! 154:
! 155: : BEGIN ( compilation -- dest ; run-time -- ) \ core
! 156: begin-like cs-push-part dest ; immediate restrict
! 157:
! 158: Defer again-like ( dest -- addr )
! 159: ' nip IS again-like
! 160:
! 161: : AGAIN ( compilation dest -- ; run-time -- ) \ core-ext
! 162: dest? again-like POSTPONE branch <resolve ; immediate restrict
! 163:
! 164: Defer until-like
! 165: : until, ( list addr xt1 xt2 -- ) drop compile, <resolve drop ;
! 166: ' until, IS until-like
! 167:
! 168: : UNTIL ( compilation dest -- ; run-time f -- ) \ core
! 169: dest? ['] ?branch ['] ?branch-lp+!# until-like ; immediate restrict
! 170:
! 171: : WHILE ( compilation dest -- orig dest ; run-time f -- ) \ core
! 172: POSTPONE if
! 173: 1 cs-roll ; immediate restrict
! 174:
! 175: : REPEAT ( compilation orig dest -- ; run-time -- ) \ core
! 176: POSTPONE again
! 177: POSTPONE then ; immediate restrict
! 178:
! 179: \ counted loops
! 180:
! 181: \ leave poses a little problem here
! 182: \ we have to store more than just the address of the branch, so the
! 183: \ traditional linked list approach is no longer viable.
! 184: \ This is solved by storing the information about the leavings in a
! 185: \ special stack.
! 186:
! 187: \ !! remove the fixed size limit. 'Tis not hard.
! 188: 20 constant leave-stack-size
! 189: create leave-stack 60 cells allot
! 190: Avariable leave-sp leave-stack 3 cells + leave-sp !
! 191:
! 192: : clear-leave-stack ( -- )
! 193: leave-stack leave-sp ! ;
! 194:
! 195: \ : leave-empty? ( -- f )
! 196: \ leave-sp @ leave-stack = ;
! 197:
! 198: : >leave ( orig -- )
! 199: \ push on leave-stack
! 200: leave-sp @
! 201: dup [ leave-stack 60 cells + ] Aliteral
! 202: >= abort" leave-stack full"
! 203: tuck ! cell+
! 204: tuck ! cell+
! 205: tuck ! cell+
! 206: leave-sp ! ;
! 207:
! 208: : leave> ( -- orig )
! 209: \ pop from leave-stack
! 210: leave-sp @
! 211: dup leave-stack <= IF
! 212: drop 0 0 0 EXIT THEN
! 213: cell - dup @ swap
! 214: cell - dup @ swap
! 215: cell - dup @ swap
! 216: leave-sp ! ;
! 217:
! 218: : DONE ( compilation orig -- ; run-time -- ) \ gforth
! 219: \ !! the original done had ( addr -- )
! 220: drop >r drop
! 221: begin
! 222: leave>
! 223: over r@ u>=
! 224: while
! 225: POSTPONE then
! 226: repeat
! 227: >leave rdrop ; immediate restrict
! 228:
! 229: : LEAVE ( compilation -- ; run-time loop-sys -- ) \ core
! 230: POSTPONE ahead
! 231: >leave ; immediate restrict
! 232:
! 233: : ?LEAVE ( compilation -- ; run-time f | f loop-sys -- ) \ gforth question-leave
! 234: POSTPONE 0= POSTPONE if
! 235: >leave ; immediate restrict
! 236:
! 237: : DO ( compilation -- do-sys ; run-time w1 w2 -- loop-sys ) \ core
! 238: POSTPONE (do)
! 239: POSTPONE begin drop do-dest
! 240: ( 0 0 0 >leave ) ; immediate restrict
! 241:
! 242: : ?do-like ( -- do-sys )
! 243: ( 0 0 0 >leave )
! 244: >mark >leave
! 245: POSTPONE begin drop do-dest ;
! 246:
! 247: : ?DO ( compilation -- do-sys ; run-time w1 w2 -- | loop-sys ) \ core-ext question-do
! 248: POSTPONE (?do) ?do-like ; immediate restrict
! 249:
! 250: : +DO ( compilation -- do-sys ; run-time n1 n2 -- | loop-sys ) \ gforth plus-do
! 251: POSTPONE (+do) ?do-like ; immediate restrict
! 252:
! 253: : U+DO ( compilation -- do-sys ; run-time u1 u2 -- | loop-sys ) \ gforth u-plus-do
! 254: POSTPONE (u+do) ?do-like ; immediate restrict
! 255:
! 256: : -DO ( compilation -- do-sys ; run-time n1 n2 -- | loop-sys ) \ gforth minus-do
! 257: POSTPONE (-do) ?do-like ; immediate restrict
! 258:
! 259: : U-DO ( compilation -- do-sys ; run-time u1 u2 -- | loop-sys ) \ gforth u-minus-do
! 260: POSTPONE (u-do) ?do-like ; immediate restrict
! 261:
! 262: : FOR ( compilation -- do-sys ; run-time u -- loop-sys ) \ gforth
! 263: POSTPONE (for)
! 264: POSTPONE begin drop do-dest
! 265: ( 0 0 0 >leave ) ; immediate restrict
! 266:
! 267: \ LOOP etc. are just like UNTIL
! 268:
! 269: : loop-like ( do-sys xt1 xt2 -- )
! 270: >r >r 0 cs-pick swap cell - swap 1 cs-roll r> r> rot do-dest?
! 271: until-like POSTPONE done POSTPONE unloop ;
! 272:
! 273: : LOOP ( compilation do-sys -- ; run-time loop-sys1 -- | loop-sys2 ) \ core
! 274: ['] (loop) ['] (loop)-lp+!# loop-like ; immediate restrict
! 275:
! 276: : +LOOP ( compilation do-sys -- ; run-time loop-sys1 n -- | loop-sys2 ) \ core plus-loop
! 277: ['] (+loop) ['] (+loop)-lp+!# loop-like ; immediate restrict
! 278:
! 279: \ !! should the compiler warn about +DO..-LOOP?
! 280: : -LOOP ( compilation do-sys -- ; run-time loop-sys1 u -- | loop-sys2 ) \ gforth minus-loop
! 281: ['] (-loop) ['] (-loop)-lp+!# loop-like ; immediate restrict
! 282:
! 283: \ A symmetric version of "+LOOP". I.e., "-high -low ?DO -inc S+LOOP"
! 284: \ will iterate as often as "high low ?DO inc S+LOOP". For positive
! 285: \ increments it behaves like "+LOOP". Use S+LOOP instead of +LOOP for
! 286: \ negative increments.
! 287: : S+LOOP ( compilation do-sys -- ; run-time loop-sys1 n -- | loop-sys2 ) \ gforth s-plus-loop
! 288: ['] (s+loop) ['] (s+loop)-lp+!# loop-like ; immediate restrict
! 289:
! 290: : NEXT ( compilation do-sys -- ; run-time loop-sys1 -- | loop-sys2 ) \ gforth
! 291: ['] (next) ['] (next)-lp+!# loop-like ; immediate restrict
! 292:
! 293: \ Structural Conditionals 12dec92py
! 294:
! 295: Defer exit-like ( -- )
! 296: ' noop IS exit-like
! 297:
! 298: : EXIT ( compilation -- ; run-time nest-sys -- ) \ core
! 299: exit-like
! 300: POSTPONE ;s
! 301: POSTPONE unreachable ; immediate restrict
! 302:
! 303: : ?EXIT ( -- ) ( compilation -- ; run-time nest-sys f -- | nest-sys ) \ gforth
! 304: POSTPONE if POSTPONE exit POSTPONE then ; immediate restrict
! 305:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>