Advertisement
Guest User

ANS-compatible FORmula TRANslator

a guest
Apr 10th, 2024
32
0
139 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.21 KB | None | 0 0
  1. \ ** indicates changes for DX-Forth
  2.  
  3. empty forth definitions decimal application \ **
  4.  
  5. warning off
  6.  
  7. \ ******** ANS-compatible FORmula TRANslator ********
  8. \ see ftrandoc.txt for instructions
  9. \ ---------------------------------------------------
  10. \ ® Copyright 2004 Julian V. Noble. \
  11. \ Permission is granted by the author to \
  12. \ use this software for any application pro- \
  13. \ vided this copyright notice is preserved. \
  14. \ ---------------------------------------------------
  15.  
  16. \ program begins here
  17.  
  18. \ FORTH-WORDLIST SET-CURRENT \ a precaution
  19.  
  20. INCLUDE complex.f \ complex arithmetic package
  21. INCLUDE vector1.f \ vectoring package
  22. INCLUDE fsm2.f \ finite state machine
  23. INCLUDE chr_tbl.f \ character encoding pkg
  24.  
  25. marker -FTRAN
  26.  
  27. : ?exit ( flag) POSTPONE IF
  28. POSTPONE EXIT
  29. POSTPONE THEN ; IMMEDIATE
  30.  
  31. \ raising to integer powers
  32. [undefined] f^2 [IF] : f^2 FDUP F* ; [THEN]
  33. : f^3 FDUP FDUP F* F* ;
  34. : f^4 f^2 f^2 ;
  35.  
  36. \ increment if true ( ptr f -- ptr+1 | ptr)
  37. : ?inc S" 1 AND + " EVALUATE ; IMMEDIATE
  38.  
  39.  
  40. \ WORDLIST CONSTANT ftran \ create separate wordlist
  41. \ ftran SET-CURRENT \ for FOR...TRAN... def'ns
  42. \ GET-ORDER ftran SWAP 1+ SET-ORDER \ make ftran findable
  43.  
  44. \ -------------------------------------------- string manipulation
  45. : $ends ( c-adr -- end beg) \ convert c-adr to ends
  46. COUNT DUP 0> ( beg n f)
  47. -1 AND + ( beg n-1|0)
  48. OVER + SWAP ; ( end beg)
  49.  
  50. : ends->count ( end beg -- c-adr u) TUCK - 1+ ;
  51.  
  52. 0 value dst
  53. 0 value n
  54. 0 value src
  55.  
  56. : concat ( src u dst --) \ append u chars from src to dst
  57. \ ** LOCALS| dst n src |
  58. to dst to n to src
  59. src dst CELL+ dst @ + n CMOVE
  60. n dst @ + dst ! ;
  61. \ ---------------------------------------- end string manipulation
  62.  
  63.  
  64. \ ------------------------------------------------ data structures
  65. \ 1. String-pointer stack:
  66. \ 3 cells wide, cell at base_adr holds $ptr
  67.  
  68. 16 CONSTANT max_depth \ this seems enough
  69.  
  70. \ $ stack space + 1 cell for pointer
  71. CREATE $stack max_depth 3 * CELLS CELL+ ALLOT
  72.  
  73. HERE $stack - 1 CELLS - CONSTANT $max \ max depth (cells)
  74.  
  75. : $init -3 CELLS $stack ! ; $init
  76.  
  77. : $ptr ( -- adr offset) $stack DUP @ ;
  78.  
  79. : $lbound ( offset) 0< ABORT" empty $stack!" ;
  80.  
  81. : ($pop) ( adr offset -- end beg op)
  82. DUP $lbound \ bounds check
  83. + CELL+ ( adr[TO$])
  84. DUP >R CELL+ 2@ R> @ ; ( end beg op)
  85.  
  86. : $pop ( -- end beg op)
  87. $ptr ( adr offset)
  88. ($pop) ( end beg op)
  89. -3 CELLS $stack +! ; \ dec $ptr
  90.  
  91. : $ubound ( offset) $max > ABORT" $stack too deep!" ;
  92.  
  93. : $push ( end beg op -- )
  94. 3 CELLS $stack +! \ inc $ptr
  95. $ptr ( end beg op adr offset)
  96. DUP $ubound \ bounds check
  97. + CELL+ DUP >R ( end beg op adr[TO$])
  98. ! R> CELL+ 2! ;
  99.  
  100. \ 2. Null string
  101. CREATE bl$ 1 C, BL C,
  102. bl$ $ends 2CONSTANT 0null
  103.  
  104. \ 3. re-vectorable dummy names
  105. DEFER expr \ for indirect recursion
  106. DEFER term
  107. DEFER factor
  108.  
  109. DEFER .op \ for compilation
  110. DEFER do_id
  111. DEFER try_fp#
  112. DEFER .fp#
  113. DEFER do_@
  114. DEFER do_^
  115. DEFER do_fn
  116.  
  117. \ 4. place to make output string
  118. CREATE out_pad 512 CHARS CELL+ ALLOT \ long output $
  119.  
  120. \ -------------------------------------------- end data structures
  121.  
  122.  
  123. \ -------------------------------------------------- formula input
  124. CREATE in_pad 256 ALLOT
  125. 0 in_pad C!
  126.  
  127. \ Get character from input stream. From Wil Baden's opg .
  128. : get-char ( -- char | 0 for EOL | negative for EOF )
  129. SOURCE ( -- start_of_input #chars)
  130. >IN @ ( -- start_of_input #chars input_ptr)
  131. > IF >IN @ CHARS + C@ 1 >IN +!
  132. ELSE DROP REFILL 0=
  133. THEN ;
  134.  
  135. : +c! ( n c-adr --) \ add n to the char at c-adr
  136. TUCK C@ + SWAP C! ;
  137.  
  138. : append_char ( c c-adr --) \ append 1 char to a counted string
  139. 1 OVER +c! \ increment count
  140. DUP C@ + C! ; \ get new address and store
  141.  
  142. VARIABLE {}level
  143.  
  144. : >0,4 {}level @ 0> 4 AND ; ( -- 0 | 4)
  145.  
  146. : copy ( c --) in_pad append_char ;
  147. : copy&inc ( c --) copy 1 {}level +! ;
  148. : copy&dec ( c --) copy -1 {}level +! ;
  149.  
  150. : err0 CR ." right } before left {" ABORT ;
  151. : err1 CR ." left { between right }'s" ABORT ;
  152. : err2 CR ." no chars betw. successive {'s or }'s" ABORT ;
  153. : err3 CR ." last char before 1st } must be blank" ABORT ;
  154. : err4 CR ." first char after last { must be blank" ABORT ;
  155.  
  156. 4 wide fsm: put_char ( c col# --)
  157. \ input other | bl | { | }
  158. \ state -----------------------------------------------------------
  159. ( 0) || copy >0 || DROP >0 || copy&inc >1 || err0 >5
  160. ( 1) || err4 >6 || copy >2 || copy&inc >1 || err3 >6
  161. ( 2) || copy >2 || copy >3 || err2 >5 || err3 >6
  162. ( 3) || copy >2 || copy >3 || err2 >5 || copy&dec >0,4
  163. ( 4) || err3 >6 || err2 >6 || err1 >5 || copy&dec >0,4
  164. ( 5) ( abnormal termination w/ error0 or error1 )
  165. ( 6) ( abnormal termination w/ error2 or error3 )
  166. ;fsm
  167.  
  168. : [put_char] ( c -- col#) \ char -> col #: in out
  169. 1 OVER BL = AND ( -- c n) \ other 0
  170. OVER [CHAR] { = 2 AND + ( -- c n) \ bl 1
  171. SWAP [CHAR] } = 3 AND + ( -- #) \ { 2
  172. ; \ } 3
  173.  
  174. 0 VALUE ()level
  175. : count_parens ( c -- c )
  176. DUP [CHAR] ( = 1 AND
  177. OVER [CHAR] ) = -1 AND + ( -- c n)
  178. ()level + TO ()level ;
  179.  
  180.  
  181. : get_formula
  182. {}level OFF
  183. in_pad OFF
  184. 0 >state put_char
  185. BEGIN get-char count_parens
  186. DUP [CHAR] " <>
  187. WHILE DUP 0>
  188. IF DUP [put_char] put_char
  189. ELSE DROP THEN
  190. REPEAT DROP
  191. ()level 0<> ABORT" Unbalanced parentheses!" ;
  192.  
  193.  
  194. \ ---------------------------------------------- end formula input
  195.  
  196. \ ---------------------------------------------- conversion tables
  197. : 'dfa ' >BODY ;
  198.  
  199. 128 char_table: [token] \ convert ASCII char to token
  200. \ "other" -> 0
  201. 1 'dfa [token] CHAR Z CHAR A install
  202. 1 'dfa [token] CHAR z CHAR a install
  203.  
  204. \ modified January 8th, 2004
  205. 1 'dfa [token] CHAR [ + C! \ for address passing
  206. 1 'dfa [token] CHAR ] + C! \ for address passing
  207.  
  208. 2 'dfa [token] CHAR E CHAR D install
  209. 2 'dfa [token] CHAR e CHAR d install
  210. 3 'dfa [token] CHAR 9 CHAR 0 install
  211. 4 'dfa [token] CHAR . + C!
  212. 5 'dfa [token] CHAR ( + C!
  213. 6 'dfa [token] CHAR { + C!
  214. 7 'dfa [token] CHAR } + C!
  215. 8 'dfa [token] CHAR ) + C!
  216. 9 'dfa [token] CHAR + + C!
  217. 10 'dfa [token] CHAR - + C!
  218. 11 'dfa [token] CHAR * + C!
  219. 12 'dfa [token] CHAR / + C!
  220. 13 'dfa [token] CHAR ^ + C!
  221. 15 'dfa [token] CHAR = + C!
  222. 17 'dfa [token] CHAR , + C!
  223. \ ------------------------------------------ end conversion tables
  224.  
  225. \ -------------------------------------------------- finding stuff
  226. \ terminology: (end,beg) = pointers to substring
  227. \ op = operator token
  228.  
  229. : skip_name ( end beg --)
  230. DUP C@ [token] 1 3 WITHIN \ 1st char a letter or [ ?
  231. IF BEGIN DUP C@ [token] 1 4 WITHIN \ skip letters or digits
  232. WHILE 1+ REPEAT
  233. ELSE CR ." A proper name must begin with a letter!" ABORT
  234. THEN ;
  235.  
  236. 0 value level
  237. 0 value c2
  238. 0 value c1
  239.  
  240. : [skip] ( end beg c1 c2 -- end beg')
  241. \ ** 0 LOCALS| level c2 c1 |
  242. 0 to level to c2 to c1
  243. DUP C@ c1 <> ?exit \ 1st char <> c1
  244. BEGIN DUP C@
  245. CASE
  246. c1 OF 1 level + TO level ENDOF
  247. c2 OF -1 level + TO level ENDOF
  248. ENDCASE
  249. 1+ ( end beg')
  250. DUP C@ c2 <> \ next char <> c2
  251. level 0> INVERT AND \ and level <= 0
  252. >R 2DUP < R> OR \ or past end of string
  253. UNTIL
  254. ;
  255.  
  256. : skip_{} ( end beg -- end beg') [CHAR] { [CHAR] } [skip] ;
  257.  
  258. : skip_() ( end beg -- end beg') [CHAR] ( [CHAR] ) [skip] ;
  259.  
  260. : skip_digits ( adr -- adr') \ skip digits rightward
  261. BEGIN DUP C@ [CHAR] 0 [CHAR] 9 1+ WITHIN
  262. WHILE 1+ REPEAT ;
  263.  
  264. : skip_dp ( adr -- adr|adr+1) \ skip decimal point
  265. DUP C@ [CHAR] . = ?inc ;
  266.  
  267. : skip+ ( adr -- adr|adr+1) \ skip + sign
  268. DUP C@ [CHAR] + = ?inc ;
  269.  
  270. : skip- ( adr -- adr|adr+1) \ skip - sign
  271. DUP C@ [CHAR] - = ?inc ;
  272.  
  273. : skip_fp# ( adr -- adr') \ skip past a fp#
  274. skip_digits skip_dp skip_digits \ skip mantissa
  275. DUP C@ [token] 2 = \ d,D,e or E ?
  276. IF 1+ ELSE EXIT THEN
  277. skip+ skip- skip_digits ; \ skip exponent
  278.  
  279. : pass_thru ( end beg -- end beg')
  280. skip- \ ignore leading -
  281. DUP C@ [token] CASE
  282. 3 OF skip_fp# ENDOF \ digit
  283. 4 OF skip_fp# ENDOF \ dec. pt.
  284. 1 OF skip_name \ letter
  285. skip_{}
  286. skip_() ENDOF
  287. 2 OF skip_name \ dDeE
  288. skip_{}
  289. skip_() ENDOF
  290. 5 OF skip_() ENDOF \ left paren: (
  291. ENDCASE
  292. ;
  293.  
  294.  
  295. : [op] ( char -- token) \ in out
  296. [token] \ "other" 0
  297. 7 - DUP 0> AND 2/ ; \ + or - 1
  298. \ * or / 2
  299. \ ^ 3
  300. \ = 4
  301. \ , 5
  302.  
  303. : op_find ( end beg c -- adr | 0) \ find exposed operator
  304. [op] >R ( end beg) \ save op token
  305. BEGIN pass_thru \ ignore id's, fp#'s, fn's, (expr)'s
  306. DUP C@ [op] R@ <> \ op not found
  307. >R 2DUP > R> AND \ and not done
  308. WHILE 1+ \ incr. ptr
  309. REPEAT TUCK > AND ( -- adr | 0)
  310. R> DROP \ clean up
  311. ;
  312.  
  313. \ ---------------------------------------------- end finding stuff
  314.  
  315. \ -------------------------------------------------------- parsing
  316.  
  317. : assign \ assign -> id = expr | id = | expr
  318. $init
  319. out_pad OFF
  320. in_pad $ends 2DUP [CHAR] = op_find ( end beg ptr|0)
  321. ?DUP IF 1- TUCK >R [CHAR] = $push \ id = expr
  322. ( end) R> 2 + BL $push expr
  323. ELSE OVER C@ [CHAR] = = \ id =
  324. IF SWAP 1- SWAP [CHAR] =
  325. ELSE BL THEN \ expr
  326. $push
  327. THEN
  328. expr
  329. ;
  330.  
  331. 0 value ptr
  332. 0 value op
  333. 0 value beg
  334. 0 value end
  335.  
  336. : <expr> \ expr -> term | term & expr
  337. \ ** $pop LOCALS| op beg end |
  338. end >r beg >r op >r
  339. $pop to op to beg to end
  340. end beg [CHAR] + op_find ( ptr | false)
  341. ?DUP IF ( ptr) DUP c@ >R \ save op'
  342. \ $stack:
  343. ( ptr) end OVER 1+ R> $push \ expr' op'
  344. ( ptr) 1- beg op $push \ term op
  345. term RECURSE
  346. ELSE end beg op $push term \ term op
  347. THEN
  348. r> to op r> to beg r> to end
  349. ;
  350.  
  351. \ 0 value op
  352. \ 0 value beg
  353. \ 0 value end
  354.  
  355. : <term> \ term -> factor | factor % term
  356. \ ** $pop LOCALS| op beg end |
  357. end >r beg >r op >r
  358. $pop to op to beg to end
  359. end beg [CHAR] * op_find ( ptr true | false)
  360. ?DUP IF ( ptr) DUP c@ >R \ save op'
  361. \ $stack:
  362. 0NULL op $push \ null op
  363. end OVER 1+ R> $push \ term' op'
  364. ( ptr) 1- beg BL $push \ factor bl
  365. factor RECURSE
  366. ELSE end beg op $push
  367. THEN
  368. factor
  369. r> to op r> to beg r> to end
  370. ;
  371.  
  372. \ -------------- auxiliary words for parsing factor --------------
  373. : <do_F@> S" F@ " ;
  374. : <do_z@> S" z@ " ;
  375.  
  376. \ 0 value op
  377. \ 0 value beg
  378. \ 0 value end
  379.  
  380. : <do_id> ( end beg op -- op)
  381. \ ** LOCALS| op beg end |
  382. end >r beg >r op >r
  383. to op to beg to end
  384. op [CHAR] = = \ op is =
  385. end beg 0null D= \ $ is 0null
  386. OR INVERT \ true if neither
  387. >R \ defer flag
  388.  
  389. \ modification for address-passing, January 8th, 2004
  390. beg C@ [CHAR] [ = \ enclosed in [] ?
  391. end C@ [CHAR] ] = AND \
  392. >R \ defer flag
  393. R@ IF beg 1+ TO beg \ remove []
  394. end 1- TO end
  395. THEN
  396. R> INVERT \ not in []
  397.  
  398. end beg ends->count do_id
  399. R> AND \ not =, and not null$
  400. IF do_@ do_id THEN op
  401. r> to op r> to beg r> to end
  402. ;
  403.  
  404. : leading-? ( adr -- f)
  405. DUP C@ [CHAR] - = SWAP 1+ C@ [token] 3 <> AND ;
  406.  
  407. : $fneg S" FNEGATE " ;
  408. : $zneg S" znegate " ;
  409.  
  410. DEFER neg$ ' $fneg IS neg$
  411.  
  412. \ 0 value op
  413. \ 0 value beg
  414. \ 0 value end
  415.  
  416. : try_id ( op end beg -- f) \ true => $ was an id
  417. \ ** LOCALS| beg end op |
  418. end >r beg >r op >r
  419. to beg to end to op
  420. beg skip- C@ [token] 1 3 WITHIN \ begins with letter
  421. beg C@ BL = OR \ or a blank
  422. end C@ [CHAR] ) <> AND \ doesn't end with )
  423. DUP
  424. IF end beg skip- op <do_id> .op \ was an id
  425. beg C@ [CHAR] - =
  426. IF neg$ do_fn THEN
  427. THEN \ wasn't an id
  428. r> to op r> to beg r> to end
  429. ;
  430.  
  431.  
  432. : <try_fp#> ( op end beg -- f) \ true => $ was a fp#
  433. ends->count >FLOAT
  434. IF .fp# .op TRUE ELSE DROP FALSE THEN
  435. ;
  436.  
  437.  
  438. : <try_z#> ( op end beg -- f) \ true => $ was a fp#
  439. ends->count >FLOAT
  440. IF 0e0 .fp# .op TRUE ELSE DROP FALSE THEN
  441. ;
  442.  
  443. : enclosed? ( end beg -- f)
  444. C@ [CHAR] ( = SWAP
  445. C@ [CHAR] ) = AND ;
  446.  
  447. \ 0 value op
  448. \ 0 value beg
  449. \ 0 value end
  450.  
  451. : try_(expr) ( op end beg -- f) \ true => $ was (expr)
  452. \ ** LOCALS| beg end op |
  453. end >r beg >r op >r
  454. to beg to end to op
  455. end beg enclosed?
  456. IF 0null op $push end 1- beg 1+ BL $push
  457. expr factor TRUE
  458. ELSE FALSE THEN
  459. r> to op r> to beg r> to end
  460. ;
  461.  
  462.  
  463. : <do_f^> ( n --)
  464. CASE 1 OF S" " ENDOF
  465. 2 OF S" f^2 " ENDOF
  466. 3 OF S" f^3 " ENDOF
  467. 4 OF S" f^4 " ENDOF
  468. ENDCASE do_id
  469. ;
  470.  
  471. : <do_z^> ( n --)
  472. CASE 1 OF S" " ENDOF
  473. 2 OF S" z^2 " ENDOF
  474. 3 OF S" z^3 " ENDOF
  475. 4 OF S" z^4 " ENDOF
  476. ENDCASE do_id
  477. ;
  478.  
  479. : int<5? ( end beg -- n TRUE | FALSE)
  480. ends->count 0 0 2SWAP >NUMBER ( d adr 0 | d' adr' n)
  481. 0= IF 2DROP DUP 1 5 WITHIN ( n f --)
  482. ELSE 2DROP FALSE THEN ;
  483.  
  484. \ 0 value ptr
  485. \ 0 value op
  486. \ 0 value beg
  487. \ 0 value end
  488.  
  489. : try_f1^f2 ( op end beg -- f) \ true => $ was f^f
  490. \ ** 0 LOCALS| ptr beg end op |
  491. ptr >r end >r beg >r op >r
  492. 0 to ptr to beg to end to op
  493. end beg skip- [CHAR] ^ op_find TO ptr
  494. ptr
  495. IF 0null op $push \ push operator
  496. end ptr 1+ int<5? \ is f2 an integer < 5
  497. IF ptr 1- beg skip- \ parse f1^n
  498. BL $push
  499. factor do_^
  500. ELSE DROP \ clear stack
  501. end ptr 1+ [CHAR] ^ $push \ f2
  502. ptr 1- beg skip- BL $push \ push f1
  503. factor factor
  504. THEN factor
  505. beg C@ [CHAR] - = IF neg$ do_fn THEN
  506. THEN ptr 0<> ( flag)
  507. r> to op r> to beg r> to end r> to ptr
  508. ;
  509.  
  510. create func 12 allot
  511.  
  512. : C"
  513. postpone s" func postpone literal postpone pack ; immediate
  514.  
  515. : func_lib ( xt -- c-adr)
  516. CASE
  517. ['] FABS OF C" FABS " ENDOF
  518. ['] FACOS OF C" FACOS " ENDOF
  519. [DEFINED] FACOSH [IF] ['] FACOSH OF C" FACOSH " ENDOF [THEN]
  520. ['] FASIN OF C" FASIN " ENDOF
  521. [DEFINED] FASINH [IF] ['] FASINH OF C" FASINH " ENDOF [THEN]
  522. ['] FATAN OF C" FATAN " ENDOF
  523. ['] FATAN2 OF C" FATAN2 " ENDOF
  524. [DEFINED] FATANH [IF] ['] FATANH OF C" FATANH " ENDOF [THEN]
  525. ['] FCOS OF C" FCOS " ENDOF
  526. [DEFINED] FCOSH [IF] ['] FCOSH OF C" FCOSH " ENDOF [THEN]
  527. ['] FEXP OF C" FEXP " ENDOF
  528. ['] FLN OF C" FLN " ENDOF
  529. ['] FMAX OF C" FMAX " ENDOF
  530. ['] FMIN OF C" FMIN " ENDOF
  531. ['] FSIN OF C" FSIN " ENDOF
  532. [DEFINED] FSINH [IF] ['] FSINH OF C" FSINH " ENDOF [THEN]
  533. ['] FTAN OF C" FTAN " ENDOF
  534. ['] FSQRT OF C" FSQRT " ENDOF
  535. [DEFINED] FTANH [IF] ['] FTANH OF C" FTANH " ENDOF [THEN]
  536. ENDCASE
  537. ;
  538.  
  539. [undefined] CAPS-FIND [IF]
  540. : lcase? ( char -- flag=true if lower case)
  541. DUP [CHAR] a MAX ( char max[a,c])
  542. SWAP [CHAR] z MIN ( max[a,c] min[a,z])
  543. = ;
  544.  
  545. : ucase ( c-adr u --) OVER + SWAP
  546. DO I C@ DUP lcase? 32 AND - I C! LOOP ;
  547. \ assumes ASCII character coding
  548. : CAPS-FIND DUP COUNT ucase FIND ;
  549. [THEN]
  550.  
  551. : Fname ( end beg -- xt TRUE | c-adr FALSE)
  552. \ add leading F to fn.name and look up
  553. >R 1+ R> ( end+1 beg)
  554. 1 PAD C! [CHAR] F PAD 1+ C!
  555. PAD 1+ -ROT ( pad+1 end+1 beg)
  556. DO 1+ I C@ OVER C! \ append char to PAD
  557. 1 PAD +c! \ incr. count at PAD
  558. LOOP DROP
  559. PAD CAPS-FIND 0<>
  560. ;
  561.  
  562. : list! ( --)
  563. $pop >R \ defer op
  564. 2DUP [CHAR] , op_find ( end beg ptr|0) \ -> )comma(
  565. ?DUP IF ROT OVER 1+ ( beg ptr end ptr+1)
  566. BL $push ( beg ptr)
  567. 1- SWAP BL $push
  568. expr RECURSE
  569. ELSE BL $push expr \ only 1 arg
  570. THEN
  571. R> .op \ emit op
  572. ;
  573.  
  574. \ 0 value ptr
  575. \ 0 value op
  576. \ 0 value beg
  577. \ 0 value end
  578.  
  579. : try_func ( op end beg -- f) \ fn -> id arglist
  580. \ ** 0 LOCALS| ptr beg end op |
  581. ptr >r end >r beg >r op >r
  582. 0 to ptr to beg to end to op
  583. end beg skip- skip_name ( end beg')
  584. DUP TO ptr ( end ptr)
  585. enclosed? DUP \ looks like a function
  586. IF ptr 1- beg skip- ( end' beg|beg+1)
  587. Fname \ look up F+fn.name
  588. beg C@ [CHAR] - = >R \ defer possible NEGATE
  589. IF func_lib $ends ( end beg) \ library fn
  590. ELSE DROP
  591. ptr 1- beg skip- ( end beg) \ other
  592. THEN op $push \ push function name
  593. end 1- ptr 1+ BL $push \ push arg list
  594. list! \ handle arg list
  595. $pop -ROT ends->count do_fn .op
  596. R> IF neg$ do_fn THEN
  597. THEN
  598. r> to op r> to beg r> to end r> to ptr
  599. ;
  600.  
  601. \ ---------------- end auxiliary words for factor ----------------
  602.  
  603. \ 0 value op
  604. \ 0 value beg
  605. \ 0 value end
  606.  
  607. : <factor> \ factor -> id | fp# | ( expr ) | f^f | function
  608. \ ** $pop LOCALS| op beg end | \ true => success
  609. \ end >r beg >r op >r
  610. $pop to op to beg to end \ true => success
  611. op end beg try_f1^f2 ?exit
  612. op end beg try_id ?exit
  613. op end beg try_fp# ?exit
  614. op end beg try_(expr) ?exit
  615. op end beg try_func ?exit
  616. ." Not a factor!" ABORT
  617. \ r> to op r> to beg r> to end
  618. ;
  619.  
  620. \ ---------------------------------------------------- end parsing
  621.  
  622. \ --------------------------------------------------- output words
  623. : real_op ( op --) [token]
  624. CASE 9 OF S" F+ " ENDOF
  625. 10 OF S" F- " ENDOF
  626. 11 OF S" F* " ENDOF
  627. 12 OF S" F/ " ENDOF
  628. 13 OF S" F** " ENDOF
  629. 15 OF S" F! " ENDOF
  630. 0 OF S" " ENDOF
  631. ENDCASE
  632. do_fn
  633. ;
  634.  
  635. : cmplx_op ( op --) [token]
  636. CASE 9 OF S" z+ " ENDOF
  637. 10 OF S" z- " ENDOF
  638. 11 OF S" z* " ENDOF
  639. 12 OF S" z/ " ENDOF
  640. 13 OF S" z^ " ENDOF
  641. 15 OF S" z! " ENDOF
  642. 0 OF S" " ENDOF
  643. ENDCASE
  644. do_fn
  645. ;
  646.  
  647. ' <expr> IS expr \ resolve forward refs
  648. ' <term> IS term
  649. ' <factor> IS factor
  650.  
  651.  
  652. : >out ( c-adr u --) out_pad concat ; \ append to out_pad
  653.  
  654. \ FORTH-WORDLIST SET-CURRENT \ definitions to FORTH
  655.  
  656. [undefined] $ftemp [IF] CREATE $ftemp 32 CHARS ALLOT [THEN]
  657.  
  658. : f->$ ( f: r --) ( -- c-adr u)
  659. BL $ftemp C!
  660. $ftemp CHAR+ [CHAR] . OVER C! ( $ftemp+1)
  661. CHAR+ PRECISION REPRESENT ( n f1 f2)
  662. INVERT
  663. IF ." Can't convert fp# to string!" ABORT THEN
  664. IF [CHAR] - $ftemp C! THEN ( n)
  665. $ftemp PRECISION 2 + CHARS + ( n adr)
  666. [CHAR] E OVER C! \ add E
  667. CHAR+ ( n adr+1)
  668. SWAP S>D TUCK DABS <# #S ROT SIGN #> ( adr+1 c-adr u)
  669. ROT SWAP DUP >R CMOVE
  670. $ftemp PRECISION 3 + R> + CHARS ( c-adr u)
  671. do_fn
  672. ;
  673.  
  674. : (f") ( --)
  675. ['] real_op IS .op \ redirect
  676. ['] <try_fp#> IS try_fp#
  677. ['] f->$ IS .fp#
  678. ['] >out IS do_id
  679. ['] >out IS do_fn
  680. ['] <do_f@> IS do_@
  681. ['] <do_f^> IS do_^
  682. ['] $fneg IS neg$
  683.  
  684. get_formula assign
  685. out_pad DUP CELL+ SWAP @ ( c-adr u)
  686. ;
  687.  
  688. : f" (f") STATE @
  689. IF EVALUATE ELSE CR CR TYPE THEN ; IMMEDIATE
  690.  
  691. : f$" (f") EVALUATE ;
  692.  
  693. : z->$ ( f: x y --) FSWAP f->$ 0null ends->count do_fn f->$ ;
  694.  
  695. : (zz") ( --) \ can't use z" -- Win32Forth uses it!
  696. ['] cmplx_op IS .op \ redirect
  697. ['] <try_z#> IS try_fp#
  698. ['] z->$ IS .fp#
  699. ['] >out IS do_id
  700. ['] >out IS do_fn
  701. ['] <do_z@> IS do_@
  702. ['] <do_z^> IS do_^
  703. ['] $zneg IS neg$
  704.  
  705. get_formula assign
  706. out_pad DUP CELL+ SWAP @ ( c-adr u)
  707. ;
  708.  
  709. : zz" (zz") STATE @
  710. IF EVALUATE ELSE CR CR TYPE THEN
  711. ; IMMEDIATE
  712.  
  713. : zz$" (zz") EVALUATE ;
  714. \ ----------------------------------------------- end output words
  715. \ GET-ORDER NIP 1- SET-ORDER \ hide ftran definitions
  716. \ ---------------------------------------------------- end program
  717.  
  718. behead -ftran $ftemp
  719.  
  720. warning on
  721.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement