RLISP88.LOG 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449
  1. REDUCE 3.6, 15-Jul-95, patched to 6 Mar 96 ...
  2. % Test of Rlisp88 version of Rlisp. Many of these functions are taken
  3. % from the solved exercises in the book "RLISP '88: An Evolutionary
  4. % Approach to Program Design and Reuse".
  5. % Author: Jed B. Marti.
  6. on rlisp88;
  7. nil
  8. % Confidence test tries to do a little of everything. This doesn't really
  9. % test itself so you need to compare to the log file. Syntax errors on
  10. % the other hand should be cause for alarm.
  11. % ARRAYS
  12. % 1. Single dimension array.
  13. global '(v1);
  14. nil
  15. v1 := mkarray 5;
  16. [nil nil nil nil nil nil]
  17. for i:=0:5 do v1[i] := 3**i;
  18. nil
  19. v1;
  20. [1 3 9 27 81 243]
  21. % 2. 2D array.
  22. global '(v3x3);
  23. nil
  24. v3x3 := mkarray(2, 2);
  25. [[nil nil nil] [nil nil nil] [nil nil nil]]
  26. for row := 0:2 do
  27. for col := 0:2 do
  28. v3x3[row, col] := if row = col then 1.0 else 0.0;
  29. nil
  30. v3x3;
  31. [[1.0 0.0e+000 0.0e+000] [0.0e+000 1.0 0.0e+000] [0.0e+000 0.0e+000 1.0]]
  32. % 3. Triangular array.
  33. global '(tri);
  34. nil
  35. tri := mkarray 3;
  36. [nil nil nil nil]
  37. for row := 0:3 do tri[row] := mkarray row;
  38. nil
  39. for row := 0:3 do
  40. for col := 0:row do
  41. tri[row,col] := row * col;
  42. nil
  43. tri;
  44. [[0] [0 1] [0 2 4] [0 3 6 9]]
  45. % 4. ARRAY test.
  46. expr procedure rotate theta;
  47. /* Generates rotation array for angle theta (in radians) */
  48. array(array(cosd theta, - sind theta, 0.0),
  49. array(sind theta, cosd theta, 0.0),
  50. array(0.0, 0.0, 1.0));
  51. rotate
  52. rotate 45.0;
  53. [[0.70710678118655 -0.70710678118655 0.0e+000] [0.70710678118655 0.70710678118655
  54. 0.0e+000] [0.0e+000 0.0e+000 1.0]]
  55. % 5. Random elements.
  56. % Now create a vector with random elements.
  57. M3 := ARRAY('A, 3 + 4, ARRAY("String", 'ID), '(a b));
  58. [a 7 ["String" id] (a b)]
  59. M3[2, 1];
  60. id
  61. M4 := ARRAY(ARRAY('a, 'b), ARRAY('c, 'd));
  62. [[a b] [c d]]
  63. M4[1];
  64. [c d]
  65. % 6. Array addition.
  66. expr procedure ArrayAdd(a, b);
  67. if vectorp a then
  68. for i:=0:uc
  69. with c, uc
  70. initially c := mkarray(uc := upbv a)
  71. do c[i] := ArrayAdd(a[i], b[i])
  72. returns c
  73. else a + b;
  74. arrayadd
  75. ArrayAdd(array(array(array(1, 2), array(3, 4)),
  76. array(array(5, 6), array(7, 8))),
  77. array(array(array(1, 1), array(2, 2)),
  78. array(array(3, 3), array(4, 4))));
  79. [[[2 3] [5 6]] [[8 9] [11 12]]]
  80. % RECORDS
  81. % 1: Declaration.
  82. RECORD MAPF /* A MAPF record defines
  83. the contents of a MAPF file. */
  84. WITH
  85. MAPF!:NAME := "" /* Name of MAPF (a string) */,
  86. MAPF!:NUMBER := 0 /* MAPF number (integer) */,
  87. MAPF!:ROAD-COUNT := 0 /* Number of roads */,
  88. MAPF!:NODE-COUNT := 0 /* Number of nodes */,
  89. MAPF!:LLAT := 0.0 /* Lower left hand corner map latitude */,
  90. MAPF!:LLONG := 0.0 /* Lower left hand corner map longitude */,
  91. MAPF!:ULAT := 0.0 /* Upper right hand corner map latitude */,
  92. MAPF!:ULONG := 0.0 /* Upper right hand corner map longitude */;
  93. mapf
  94. % 2: Creation.
  95. global '(r1 r2 r3);
  96. nil
  97. r1 := mapf();
  98. [mapf "" 0 0 0 0.0e+000 0.0e+000 0.0e+000 0.0e+000]
  99. r2 := mapf(mapf!:name := "foobar", mapf!:road-count := 34);
  100. [mapf "foobar" 0 34 0 0.0e+000 0.0e+000 0.0e+000 0.0e+000]
  101. r3 := list('a . r1, 'b . r2);
  102. ((a . [mapf "" 0 0 0 0.0e+000 0.0e+000 0.0e+000 0.0e+000]) (b . [mapf "foobar" 0
  103. 34 0 0.0e+000 0.0e+000 0.0e+000 0.0e+000]))
  104. % 3: Accessing.
  105. mapf!:number r1;
  106. 0
  107. mapf!:road-count cdr assoc('b, r3);
  108. 34
  109. % 4: Assignment.
  110. mapf!:number r1 := 7622;
  111. 7622
  112. mapf!:road-count cdr assoc('b, r3) := 376;
  113. 376
  114. mapf!:node-count(mapf!:name r2 := mapf()) := 34;
  115. 34
  116. r2;
  117. [mapf [mapf "" 0 0 34 0.0e+000 0.0e+000 0.0e+000 0.0e+000] 0 376 0 0.0e+000
  118. 0.0e+000 0.0e+000 0.0e+000]
  119. % 5. Options.
  120. RECORD complex /* Stores complex reals */
  121. WITH
  122. R := 0.0 /* Real part */,
  123. I := 0.0 /* Imaginary part */
  124. HAS CONSTRUCTOR;
  125. complex
  126. Make-Complex(I := 34.0, R := 12.0);
  127. [complex 12.0 34.0]
  128. RECORD Rational /* Representation of rational numbers */
  129. WITH
  130. Num := 0 /* Numerator */,
  131. Den := 1 /* Denominator */
  132. HAS CONSTRUCTOR = rat;
  133. +++ num redefined as a macro
  134. +++ den redefined as a macro
  135. rational
  136. expr procedure gcd(p, q);
  137. if q > p then gcd(q, p)
  138. else (if r = 0 then q else gcd(q, r)) where r = remainder(p,q);
  139. gcd
  140. expr procedure Rational(a, b);
  141. /* Build a rational number in lowest terms */
  142. Rat(Num := a / g, Den := b / g) where g := gcd(a, b);
  143. +++ rational redefined
  144. rational
  145. Rational(34, 12);
  146. [rational 17 6]
  147. RECORD Timing /* Timing Record for RLISP test */
  148. WITH
  149. Machine := "" /* Machine name */,
  150. Storage := 0 /* Main storage in bits */,
  151. TimeMS = 0 /* Test time in milliseconds */
  152. HAS NO CONSTRUCTOR;
  153. timing
  154. % PREDICATE option.
  155. RECORD History /* Record of an event */
  156. WITH
  157. EventTime := 0.0 /* Time of event (units) */,
  158. EventData := NIL /* List with (type ...) */
  159. HAS PREDICATE = History!?;
  160. history
  161. History!? History(EventData := '(MOVE 34.5 52.5));
  162. t
  163. % FOR LOOP
  164. % 1) Basic test.
  165. EXPR PROCEDURE LPRINT lst;
  166. /* LPRINT displays each element of its argument separated by blanks.
  167. After the last element has been displayed, the print line is
  168. terminated. */
  169. FOR EACH element IN lst
  170. DO << PRIN2 element; PRINC " " >>
  171. FINALLY TERPRI()
  172. RETURNS lst;
  173. lprint
  174. LPRINT '(Now is the time to use RLISP);
  175. now is the time to use rlisp
  176. (now is the time to use rlisp)
  177. % 2) Basic iteration in both directions.
  178. FOR i:=5 STEP -2 UNTIL 0 DO PRINT i;
  179. 5
  180. 3
  181. 1
  182. nil
  183. FOR i:=1:3 DO PRINT i;
  184. 1
  185. 2
  186. 3
  187. nil
  188. % 3) COLLECT option.
  189. FOR EACH leftpart IN '(A B C)
  190. EACH rightpart IN '(1 2 "string")
  191. COLLECT leftpart . rightpart;
  192. ((a . 1) (b . 2) (c . "string"))
  193. % 4) IN/ON iterators.
  194. FOR EACH X IN '(a b c) DO PRINT x;
  195. a
  196. b
  197. c
  198. nil
  199. FOR EACH x ON '(a b c) DO PRINT x;
  200. (a b c)
  201. (b c)
  202. (c)
  203. nil
  204. % 5) EVERY option.
  205. FOR EACH x IN '(A B C) EVERY IDP x
  206. RETURNS "They are all id's";
  207. "They are all id's"
  208. FOR EACH x IN '(A B 12) EVERY IDP x
  209. RETURNS "They are all id's";
  210. nil
  211. % 6) INITIALLY/FINALLY option.
  212. EXPR PROCEDURE ListPrint x;
  213. /* ListPrint(x) displays each element of x separated by blanks. The
  214. first element is prefixed with "*** ". The last element is suffixed
  215. with a period and a new line. */
  216. FOR EACH element ON x
  217. INITIALLY PRIN2 "*** "
  218. DO << PRIN2 CAR element;
  219. IF CDR element THEN PRIN2 " " >>
  220. FINALLY << PRIN2 "."; TERPRI() >>;
  221. listprint
  222. ListPrint '(The quick brown bert died);
  223. *** the quick brown bert died.
  224. nil
  225. % 7) MAXIMIZE/MINIMIZE options.
  226. FOR EACH x IN '(A B 12 -34 2.3)
  227. WHEN NUMBERP x
  228. MAXIMIZE x;
  229. 12
  230. FOR EACH x IN '(A B 12 -34 2.3)
  231. WHEN NUMBERP x
  232. MINIMIZE x;
  233. -34
  234. % 8) RETURNS option.
  235. EXPR PROCEDURE ListFiddle(f, x);
  236. /* ListFiddle displays every element of its second argument and returns
  237. a list of those for which the first argument returns non-NIL. */
  238. FOR EACH element IN x
  239. WITH clist
  240. DO << PRINT element;
  241. IF APPLY(f, LIST element) THEN clist := element . clist >>
  242. RETURNS REVERSIP clist;
  243. listfiddle
  244. ListFiddle(FUNCTION ATOM, '(a (BANG 12) "OOPS!"));
  245. a
  246. (bang 12)
  247. "OOPS!"
  248. (a "OOPS!")
  249. % 9) SOME option.
  250. FOR EACH x IN '(a b 12) SOME NUMBERP x
  251. DO PRINT x;
  252. a
  253. b
  254. t
  255. % 10) UNTIL/WHILE options.
  256. EXPR PROCEDURE CollectUpTo l;
  257. /* CollectUpTo collect all the elements of the list l up to the
  258. first number. */
  259. FOR EACH x IN l UNTIL NUMBERP x COLLECT x;
  260. collectupto
  261. CollectUpTo '(a b c 1 2 3);
  262. (a b c)
  263. % 11) WHEN/UNLESS options.
  264. FOR EACH x IN '(A 12 "A String" 32)
  265. WHEN NUMBERP x
  266. COLLECT x;
  267. (12 32)
  268. % ##### Basic Tests #####
  269. % Tests some very basic things that seem to go wrong frequently.
  270. % Numbers.
  271. if +1 neq 1 then error(0, "+1 doesn't parse");
  272. nil
  273. if -1 neq - 1 then error(0, "-1 doesn't parse");
  274. nil
  275. expr procedure factorial n;
  276. if n < 2 then 1 else n * factorial(n - 1);
  277. +++ factorial redefined
  278. factorial
  279. if +2432902008176640000 neq factorial 20 then
  280. error(0, "bignum + doesn't work");
  281. nil
  282. if -2432902008176640000 neq - factorial 20 then
  283. error(0, "bignum - doesn't work");
  284. nil
  285. % This actually blew up at one time.
  286. if -3.14159 neq - 3.14159 then error(0, "negative floats don't work");
  287. nil
  288. if +3.14159 neq 3.14159 then error(0, "positive floats don't work");
  289. nil
  290. % ##### Safe Functions #####
  291. % Description: A set of CAR/CDR alternatives that
  292. % return NIL when CAR/CDR of an atom is tried.
  293. expr procedure SafeCar x;
  294. /* Returns CAR of a list or NIL. */
  295. if atom x then nil else car x;
  296. safecar
  297. expr procedure SafeCdr x;
  298. /* Returns CDR of a list or NIL. */
  299. if atom x then nil else cdr x;
  300. safecdr
  301. expr procedure SafeFirst x; SafeCar x;
  302. safefirst
  303. expr procedure SafeSecond x; SafeCar SafeCdr x;
  304. safesecond
  305. expr procedure SafeThird x; SafeSecond SafeCdr x;
  306. safethird
  307. % ##### Test of Procedures #####
  308. %------------------------- Exercise #1 -------------------------
  309. expr procedure delassoc(x, a);
  310. /* Delete the element from x from the alist a non-destructively. Returns
  311. the reconstructed list. */
  312. if null a then nil
  313. else if atom a then a . delassoc(x, cdr a)
  314. else if caar a = x then cdr a
  315. else car a . delassoc(x, cdr a);
  316. delassoc
  317. if delassoc('a, '((a b) (c d))) = '((c d))
  318. then "Test 1 delassoc OK"
  319. else error(0, "Test 1 delassoc failed");
  320. "Test 1 delassoc OK"
  321. if delassoc('b, '((a b) (b c) (c d))) = '((a b) (c d))
  322. then "Test 2 delassoc OK"
  323. else error(0, "Test 2 delassoc failed");
  324. "Test 2 delassoc OK"
  325. if delassoc('c, '((a b) (b c) (c d))) = '((a b) (b c))
  326. then "Test 3 delassoc OK"
  327. else error(0, "Test 3 delassoc failed");
  328. "Test 3 delassoc OK"
  329. if delassoc('d, '((a b) (b c) (c d))) = '((a b) (b c) (c d))
  330. then "Test 4 delassoc OK"
  331. else error(0, "Test 4 delassoc failed");
  332. "Test 4 delassoc OK"
  333. %------------------------- Exercise #2 -------------------------
  334. expr procedure gcd(u, v);
  335. if v = 0 then u else gcd(v, remainder(u, v));
  336. +++ gcd redefined
  337. gcd
  338. if gcd(2, 4) = 2 then "Test 1 GCD OK" else error(0, "Test 1 GCD fails");
  339. "Test 1 GCD OK"
  340. if gcd(13, 7) = 1
  341. then "Test 2 GCD OK" else error(0, "Test 2 GCD fails");
  342. "Test 2 GCD OK"
  343. if gcd(15, 10) = 5
  344. then "Test 3 GCD OK" else error(0, "Test 3 GCD fails");
  345. "Test 3 GCD OK"
  346. if gcd(-15, 10) = -5
  347. then "Test 4 GCD OK" else error(0, "Test 4 GCD fails");
  348. "Test 4 GCD OK"
  349. if gcd(-15, 0) = -15
  350. then "Test 5 GCD OK" else error(0, "Test 5 GCD fails");
  351. "Test 5 GCD OK"
  352. %-------------------- Exercise #3 --------------------
  353. expr procedure properintersection(a, b);
  354. /* Returns the proper intersection of proper sets a and b.
  355. The set representation is a list of elements with the
  356. EQUAL relation. */
  357. if null a then nil
  358. else if car a member b then car a . properintersection(cdr a, b)
  359. else properintersection(cdr a, b);
  360. properintersection
  361. % Test an EQ intersection.
  362. properintersection('(a b), '(b c));
  363. (b)
  364. if properintersection('(a b), '(b c)) = '(b)
  365. then "Test 1 properintersection OK"
  366. else error(0, "Test 1 properintersection fails");
  367. "Test 1 properintersection OK"
  368. % Test an EQUAL intersection.
  369. properintersection('((a) b (c)), '((a) b (c)));
  370. ((a) b (c))
  371. if properintersection('((a) b (c)), '((a) b (c))) = '((a) b (c))
  372. then "Test 2 properintersection OK"
  373. else error(0, "Test 2 properintersection fails");
  374. "Test 2 properintersection OK"
  375. % Test an EQUAL intersection, out of order.
  376. properintersection('((a) b (c)), '(b (c) (a)));
  377. ((a) b (c))
  378. if properintersection('((a) b (c)), '(b (c) (a))) = '((a) b (c))
  379. then "Test 3 properintersection OK"
  380. else error(0, "Test 3 properintersection fails");
  381. "Test 3 properintersection OK"
  382. % Test an empty intersection.
  383. properintersection('((a) b (c)), '(a (b) c));
  384. nil
  385. if properintersection('((a) b (c)), '(a (b) c)) = nil
  386. then "Test 4 properintersection OK"
  387. else error(0, "Test 4 properintersection fails");
  388. "Test 4 properintersection OK"
  389. %-------------------- Exercise #4 -------------------------
  390. expr procedure TreeVisit(a, tree, c);
  391. /* Preorder visit of tree to find a. Returns path from root. c
  392. contains path to root of tree so far. */
  393. if null tree then nil
  394. else if a = car tree then append(c, {a})
  395. else TreeVisit(a, cadr tree, append(c, {car tree})) or
  396. TreeVisit(a, caddr tree, append(c, {car tree}));
  397. treevisit
  398. TreeVisit('c, '(a (b (d nil nil) (c nil nil)) (e nil nil)), nil);
  399. (a b c)
  400. if TreeVisit('c, '(a (b (d nil nil) (c nil nil)) (e nil nil)), nil)
  401. = '(a b c)
  402. then "Test 1 TreeVisit OK"
  403. else error(0, "Test 1 TreeVisit fails");
  404. "Test 1 TreeVisit OK"
  405. TreeVisit('h, '(a (b (d nil nil) (c nil nil))
  406. (e (f nil nil) (g (h nil nil) nil)) ), nil);
  407. (a e g h)
  408. if TreeVisit('h, '(a (b (d nil nil) (c nil nil))
  409. (e (f nil nil) (g (h nil nil) nil))),nil) = '(a e g h)
  410. then "Test 2 TreeVisit OK"
  411. else error(0, "Test 2 TreeVisit fails");
  412. "Test 2 TreeVisit OK"
  413. if TreeVisit('i, '(a (b (d nil nil) (c nil nil))
  414. (e (f nil nil) (g (h nil nil) nil)) ), nil) = nil
  415. then "Test 3 TreeVisit OK"
  416. else error(0, "Test 3 TreeVisit fails");
  417. "Test 3 TreeVisit OK"
  418. if TreeVisit('a, '(a (b (d nil nil) (c nil nil))
  419. (e (f nil nil) (g (h nil nil) nil)) ), nil) = '(a)
  420. then "Test 4 TreeVisit OK"
  421. else error(0, "Test 4 TreeVisit fails");
  422. "Test 4 TreeVisit OK"
  423. if TreeVisit('e, '(a (b (d nil nil) (c nil nil))
  424. (e (f nil nil) (g (h nil nil) nil)) ), nil) = '(a e)
  425. then "Test 5 TreeVisit OK"
  426. else error(0, "Test 5 TreeVisit fails");
  427. "Test 5 TreeVisit OK"
  428. %-------------------- Exercise #5 -------------------------
  429. expr procedure lookfor(str, l);
  430. /* Search for the list str (using =) in the top level
  431. of list l. Returns str and remaining part of l if
  432. found. */
  433. if null l then nil
  434. else if lookfor1(str, l) then l
  435. else lookfor(str, cdr l);
  436. lookfor
  437. expr procedure lookfor1(str, l);
  438. if null str then t
  439. else if null l then nil
  440. else if car str = car l then lookfor1(cdr str, cdr l);
  441. lookfor1
  442. if lookfor('(n o w),'(h e l l o a n d n o w i t i s)) = '(n o w i t i s)
  443. then "Test 1 lookfor OK"
  444. else error(0, "Test 1 lookfor fails");
  445. "Test 1 lookfor OK"
  446. if lookfor('(now is), '(now we have nothing is)) = NIL
  447. then "Test 2 lookfor OK"
  448. else error(0, "Test 2 lookfor fails");
  449. "Test 2 lookfor OK"
  450. if lookfor('(now is), '(well hello!, now)) = NIL
  451. then "Test 3 lookfor OK"
  452. else error(0, "Test 3 lookfor fails");
  453. "Test 3 lookfor OK"
  454. %-------------------- Exercise #6 -------------------------
  455. expr procedure add(a, b, carry, modulus);
  456. /* Add two numbers stored as lists with digits of
  457. modulus. Carry passes the carry around. Tries to
  458. suppress leading 0's but fails with negatives. */
  459. if null a then
  460. if null b then if zerop carry then nil
  461. else {carry}
  462. else remainder(carry + car b, modulus) .
  463. add(nil, cdr b, (carry + car b) / modulus, modulus)
  464. else if null b then add(b, a, carry, modulus)
  465. else remainder(car a + car b + carry, modulus) .
  466. add(cdr a, cdr b, (car a + car b + carry) / modulus,
  467. modulus);
  468. add
  469. if add('(9 9), '(9 9), 0, 10) = '(8 9 1)
  470. then "Test 1 add OK"
  471. else error(0, "Test 1 add fails");
  472. "Test 1 add OK"
  473. if add('(-9 -9), '(9 9), 0, 10) = '(0 0)
  474. then "Test 2 add OK"
  475. else error(0, "Test 2 add fails");
  476. "Test 2 add OK"
  477. if add('(9 9 9), '(9 9 9 9), 0, 10) = '(8 9 9 0 1)
  478. then "Test 3 add OK"
  479. else error(0, "Test 3 add fails");
  480. "Test 3 add OK"
  481. if add('(99 99 99), '(99 99 99 99), 0, 100) = '(98 99 99 0 1)
  482. then "Test 4 add OK"
  483. else error(0, "Test 4 add fails");
  484. "Test 4 add OK"
  485. if add('(13 12), '(15 1), 0, 16) = '(12 14)
  486. then "Test 5 add OK"
  487. else error(0, "Test 5 add fails");
  488. "Test 5 add OK"
  489. %-------------------- Exercise #7 -------------------------
  490. expr procedure clength(l, tmp);
  491. /* Compute the length of the (possibly circular) list l.
  492. tmp is used to pass values looked at down the list. */
  493. if null l or l memq tmp then 0
  494. else 1 + clength(cdr l, l . tmp);
  495. clength
  496. if clength('(a b c), nil) = 3
  497. then "Test 1 clength OK"
  498. else error(0, "Test 1 clength fails");
  499. "Test 1 clength OK"
  500. << xxx := '(a b c); cdr lastpair xxx := xxx; nil >>;
  501. nil
  502. if clength(xxx, nil) = 3
  503. then "Test 2 clength OK"
  504. else error(0, "Test 1 clength fails");
  505. "Test 2 clength OK"
  506. if clength(append('(a b c), xxx), nil) = 6
  507. then "Test 3 clength OK"
  508. else error(0, "Test 1 clength fails");
  509. "Test 3 clength OK"
  510. %------------------------- Exercise #8 -------------------------
  511. expr procedure fringe x;
  512. /* FRINGE(X) -- returns the fringe of X (the atoms at the
  513. end of the tree structure of X). */
  514. if atom x then {x}
  515. else if cdr x then append(fringe car x, fringe cdr x)
  516. else fringe car x;
  517. fringe
  518. if fringe nil = '(NIL)
  519. then "Test 1 fringe OK"
  520. else error(0, "Test 1 fringe fails");
  521. "Test 1 fringe OK"
  522. if fringe '(a b . c) = '(a b c)
  523. then "Test 2 fringe OK"
  524. else error(0, "Test 2 fringe fails");
  525. "Test 2 fringe OK"
  526. if fringe '((((a) . b) (c . d)) . e) = '(a b c d e)
  527. then "Test 3 fringe OK"
  528. else error(0, "Test 3 fringe fails");
  529. "Test 3 fringe OK"
  530. %------------------------- Exercise #9 -------------------------
  531. expr procedure delall(x, l);
  532. /* DELALL(X, L) -- Delete all X's from the list L using EQUAL
  533. test. The list is reconstructed. */
  534. if null l then nil
  535. else if x = car l then delall(x, cdr l)
  536. else car l . delall(x, cdr l);
  537. delall
  538. if delall('X, nil) = NIL
  539. then "Test 1 delall OK"
  540. else error(0, "Test 1 delall fails");
  541. "Test 1 delall OK"
  542. if delall('X, '(X)) = NIL
  543. then "Test 2 delall OK"
  544. else error(0, "Test 2 delall fails");
  545. "Test 2 delall OK"
  546. if delall('X, '(A)) = '(A)
  547. then "Test 3 delall OK"
  548. else error(0, "Test 3 delall fails");
  549. "Test 3 delall OK"
  550. if delall('(X B), '(A (B) (X B))) = '(A (B))
  551. then "Test 4 delall OK"
  552. else error(0, "Test 4 delall fails");
  553. "Test 4 delall OK"
  554. if delall('(X B), '((X B) (X B))) = NIL
  555. then "Test 5 delall OK"
  556. else error(0, "Test 5 delall fails");
  557. "Test 5 delall OK"
  558. if delall('(X B), '((X B) X B (X B))) = '(X B)
  559. then "Test 6 delall OK"
  560. else error(0, "Test 6 delall fails");
  561. "Test 6 delall OK"
  562. % ------------------------- Exercise #10 -------------------------
  563. expr procedure startswith(prefix, word);
  564. /* STARTSWITH(PREFIX, WORD) -- Returns T if the list of
  565. characters WORD begins with the list of characters PREFIX. */
  566. if null prefix then T
  567. else if word then
  568. if car prefix eq car word then
  569. startswith(cdr prefix, cdr word);
  570. startswith
  571. if startswith('(P R E), '(P R E S I D E N T)) = T
  572. then "Test 1 startswith OK!"
  573. else error(0, "Test 1 startswith fails");
  574. "Test 1 startswith OK!"
  575. if startswith('(P R E), '(P O S T F I X)) = NIL
  576. then "Test 2 startswith OK!"
  577. else error(0, "Test 2 startswith fails");
  578. "Test 2 startswith OK!"
  579. if startswith('(P R E), '(P R E)) = T
  580. then "Test 3 startswith OK!"
  581. else error(0, "Test 3 startswith fails");
  582. "Test 3 startswith OK!"
  583. if startswith('(P R E), '(P R)) = NIL
  584. then "Test 4 startswith OK!"
  585. else error(0, "Test 4 startswith fails");
  586. "Test 4 startswith OK!"
  587. if startswith('(P R E), NIL) = NIL
  588. then "Test 5 startswith OK!"
  589. else error(0, "Test 5 startswith fails");
  590. "Test 5 startswith OK!"
  591. if startswith('(P R E), '(P P R E)) = NIL
  592. then "Test 6 startswith OK!"
  593. else error(0, "Test 6 startswith fails");
  594. "Test 6 startswith OK!"
  595. % ##### Test of Definitions #####
  596. %------------------------- Exercise #1 -------------------------
  597. expr procedure goodlist l;
  598. /* GOODLIST(L) - returns T if L is a proper list. */
  599. if null l then T
  600. else if pairp l then goodlist cdr l;
  601. goodlist
  602. if goodlist '(a b c) = T
  603. then "Test 1 goodlist OK"
  604. else error(0, "Test 1 goodlist fails");
  605. "Test 1 goodlist OK"
  606. if goodlist nil = T
  607. then "Test 2 goodlist OK"
  608. else error(0, "Test 2 goodlist fails");
  609. "Test 2 goodlist OK"
  610. if goodlist '(a . b) = NIL
  611. then "Test 3 goodlist OK"
  612. else error(0, "Test 3 goodlist fails");
  613. "Test 3 goodlist OK"
  614. %------------------------- Exercise #2 -------------------------
  615. expr procedure fmember(a, b, fn);
  616. /* FMEMBER(A, B, FN) - Returns rest of B is A is a member
  617. of B using the FN of two arguments as an equality check. */
  618. if null b then nil
  619. else if apply(fn, {a, car b}) then b
  620. else fmember(a, cdr b, fn);
  621. fmember
  622. if fmember('a, '(b c a d), function EQ) = '(a d)
  623. then "Test 1 fmember is OK"
  624. else error(0, "Test 1 fmember fails");
  625. "Test 1 fmember is OK"
  626. if fmember('(a), '((b c) (a) d), function EQ) = NIL
  627. then "Test 2 fmember is OK"
  628. else error(0, "Test 2 fmember fails");
  629. "Test 2 fmember is OK"
  630. if fmember('(a), '((b c) (a) d), function EQUAL) = '((a) d)
  631. then "Test 3 fmember is OK"
  632. else error(0, "Test 3 fmember fails");
  633. "Test 3 fmember is OK"
  634. if fmember(34, '(1 2 56 12), function LESSP) = '(56 12)
  635. then "Test 4 fmember is OK"
  636. else error(0, "Test 4 fmember fails");
  637. "Test 4 fmember is OK"
  638. %------------------------- Exercise #3-4 -------------------------
  639. expr procedure findem(l, fn);
  640. /* FINDEM(L, FN) - returns a list of elements in L that satisfy
  641. the single argument function FN. */
  642. if null l then nil
  643. else if apply(fn, {car l}) then car l . findem(cdr l, fn)
  644. else findem(cdr l, fn);
  645. findem
  646. if findem('(a 1 23 b "foo"), function idp) = '(a b)
  647. then "Test 1 findem OK!"
  648. else error(0, "Test 1 findem fails");
  649. "Test 1 findem OK!"
  650. if findem('(1 3 a (44) 12 9),
  651. function (lambda x; numberp x and x < 10)) = '(1 3 9)
  652. then "Test 2 findem OK!"
  653. else error(0, "Test 2 findem fails");
  654. "Test 2 findem OK!"
  655. %------------------------- Exercise #5 -------------------------
  656. expr procedure insert(a, l, f);
  657. /* Insert the value a into list l based on the partial ordering function
  658. f(x,y). Non-destructive insertion. */
  659. if null l then {a}
  660. else if apply(f, {car l, a}) then a . l
  661. else car l . insert(a, cdr l, f);
  662. insert
  663. % Basic ascending order sort.
  664. insert(6, '(1 5 10), function geq);
  665. (1 5 6 10)
  666. if insert(6, '(1 5 10), function geq) = '(1 5 6 10)
  667. then "Test 1 insert (>=) OK"
  668. else error(0, "Test 1 insert (>=) fails");
  669. "Test 1 insert (>=) OK"
  670. % Try inserting element at end of list.
  671. insert(11, '(1 5 10), function geq);
  672. (1 5 10 11)
  673. if insert(11, '(1 5 10), function geq) = '(1 5 10 11)
  674. then "Test 2 insert (>=) OK"
  675. else error(0, "Test 2 insert (>=) fails");
  676. "Test 2 insert (>=) OK"
  677. % Tru inserting something at the list beginning.
  678. insert(-1, '(1 5 10), function geq);
  679. (-1 1 5 10)
  680. if insert(-1, '(1 5 10), function geq) = '(-1 1 5 10)
  681. then "Test 3 insert (>=) OK"
  682. else error(0, "Test 3 insert (>=) fails");
  683. "Test 3 insert (>=) OK"
  684. % Insert into an empty list.
  685. insert('34, nil, function leq);
  686. (34)
  687. if insert(34, nil, function leq) = '(34)
  688. then "Test 4 insert (<=) OK"
  689. else error(0, "Test 4 insert (<=) fails");
  690. "Test 4 insert (<=) OK"
  691. % Use a funny insertion function for (order . any);
  692. expr procedure cargeq(a, b); car a >= car b;
  693. cargeq
  694. insert('(34 . any), '((5 . now) (20 . and) (30 . then) (40 . but)),
  695. function cargeq);
  696. ((5 . now) (20 . and) (30 . then) (34 . any) (40 . but))
  697. if insert('(34 . any), '((5 . now) (20 . and) (30 . then) (40 . but)),
  698. function cargeq) = '((5 . now) (20 . and) (30 . then) (34 . any)
  699. (40 . but))
  700. then "Test 5 insert (>=) OK"
  701. else error(0, "Test 5 insert (>=) fails");
  702. "Test 5 insert (>=) OK"
  703. % ###### FOR Loop Exercises #####
  704. %------------------------- Exercise #1 -------------------------
  705. expr procedure floatlist l;
  706. /* FLOATLIST(L) returns a list of all floating point
  707. numbers in list L. */
  708. for each x in l
  709. when floatp x
  710. collect x;
  711. floatlist
  712. if floatlist '(3 3.4 a nil) = '(3.4)
  713. then "Test 1 floatlist OK"
  714. else error(0, "Test 1 floatlist fails");
  715. "Test 1 floatlist OK"
  716. if floatlist '(3.4 1.222 1.0e22) = '(3.4 1.222 1.0e22)
  717. then "Test 2 floatlist OK"
  718. else error(0, "Test 2 floatlist fails");
  719. "Test 2 floatlist OK"
  720. if floatlist '(a b c) = NIL
  721. then "Test 3 floatlist OK"
  722. else error(0, "Test 3 floatlist fails");
  723. "Test 3 floatlist OK"
  724. %------------------------- Exercise #2 -------------------------
  725. expr procedure revpairnum l;
  726. /* REVPAIRNUM(L) returns elements of L in a pair with
  727. the CAR a number starting at length of L and working
  728. backwards.*/
  729. for i:=length l step -1 until 0
  730. each x in l
  731. collect i . x;
  732. revpairnum
  733. if revpairnum '(a b c) = '((3 . a) (2 . b) (1 . c))
  734. then "Test 1 revpairnum OK"
  735. else error(0, "Test 1 revpairnum fails");
  736. "Test 1 revpairnum OK"
  737. if revpairnum nil = nil
  738. then "Test 2 revpairnum OK"
  739. else error(0, "Test 2 revpairnum fails");
  740. "Test 2 revpairnum OK"
  741. if revpairnum '(a) = '((1 . a))
  742. then "Test 3 revpairnum OK"
  743. else error(0, "Test 3 revpairnum fails");
  744. "Test 3 revpairnum OK"
  745. %------------------------- Exercise #3 -------------------------
  746. expr procedure lflatten l;
  747. /* LFLATTEN(L) destructively flattens the list L
  748. to all levels. */
  749. if listp l then for each x in l conc lflatten x
  750. else {l};
  751. lflatten
  752. if lflatten '(a (b) c (e (e))) = '(a b c e e)
  753. then "Test 1 lflatten OK"
  754. else error(0, "Test 1 lflatten fails");
  755. "Test 1 lflatten OK"
  756. if lflatten '(a b c) = '(a b c)
  757. then "Test 2 lflatten OK"
  758. else error(0, "Test 2 lflatten fails");
  759. "Test 2 lflatten OK"
  760. if lflatten nil = nil
  761. then "Test 3 lflatten OK"
  762. else error(0, "Test 3 lflatten fails");
  763. "Test 3 lflatten OK"
  764. if lflatten '(a (b (c (d)))) = '(a b c d)
  765. then "Test 4 lflatten OK"
  766. else error(0, "Test 4 lflatten fails");
  767. "Test 4 lflatten OK"
  768. %------------------------- Exercise #4 -------------------------
  769. expr procedure realstuff l;
  770. /* REALSTUFF(L) returns the number of non-nil items in l. */
  771. for each x in l count x;
  772. realstuff
  773. if realstuff '(a b nil c) = 3
  774. then "Test 1 realstuff OK"
  775. else error(0, "Test 1 realstuff fails");
  776. "Test 1 realstuff OK"
  777. if realstuff '(nil nil nil) = 0
  778. then "Test 2 realstuff OK"
  779. else error(0, "Test 2 realstuff fails");
  780. "Test 2 realstuff OK"
  781. if realstuff '(a b c d) = 4
  782. then "Test 3 realstuff OK"
  783. else error(0, "Test 3 realstuff fails");
  784. "Test 3 realstuff OK"
  785. %------------------------- Exercise #5 -------------------------
  786. expr procedure psentence s;
  787. /* PSENTENCE(S) prints the list of "words" S with
  788. separating blanks and a period at the end. */
  789. for each w on s
  790. do << prin2 car w;
  791. if cdr w then prin2 " " else prin2t "." >>;
  792. psentence
  793. psentence '(The man in the field is happy);
  794. the man in the field is happy.
  795. nil
  796. %------------------------- Exercise #6 -------------------------
  797. expr procedure bsort v;
  798. /* BSORT(V) sorts the vector V into ascending order using
  799. bubble sort. */
  800. for i:=0:sub1 upbv v
  801. returns v
  802. do for j:=add1 i:upbv v
  803. when i neq j and v[i] > v[j]
  804. with tmp
  805. do << tmp := v[j]; v[j] := v[i]; v[i] := tmp >>;
  806. bsort
  807. xxx := [4,3,2,1, 5];
  808. [4 3 2 1 5]
  809. if bsort xxx = [1,2,3,4,5]
  810. then "Test 1 bsort OK"
  811. else error(0, "Test 1 bsort fails");
  812. "Test 1 bsort OK"
  813. xxx := [1];
  814. [1]
  815. if bsort xxx = [1]
  816. then "Test 2 bsort OK"
  817. else error(0, "Test 2 bsort fails");
  818. "Test 2 bsort OK"
  819. %------------------------- Exercise #7 -------------------------
  820. expr procedure bsortt v;
  821. /* BSORTT(V) sorts the vector V into ascending order using
  822. bubble sort. It verifies that all elements are numbers. */
  823. << for i:=0:upbv v
  824. when not numberp v[i]
  825. do error(0, {v[i], "is not a number for BSORTT"});
  826. for i:=0:sub1 upbv v
  827. returns v
  828. do for j:=add1 i:upbv v
  829. when i neq j and v[i] > v[j]
  830. with tmp
  831. do << tmp := v[j]; v[j] := v[i]; v[i] := tmp >> >>;
  832. bsortt
  833. xxx := [1,2,'a];
  834. [1 2 a]
  835. if atom errorset(quote bsortt xxx, nil, nil)
  836. then "Test 1 bsortt OK"
  837. else error(0, "Test 1 bsortt fails");
  838. "Test 1 bsortt OK"
  839. xxx := [1, 4, 3, 1];
  840. [1 4 3 1]
  841. if car errorset(quote bsortt xxx, nil, nil) = [1,1,3,4]
  842. then "Test 2 bsortt OK"
  843. else error(0, "Test 2 bsortt fails");
  844. "Test 2 bsortt OK"
  845. % ------------------------- Exercise #8 -------------------------
  846. expr procedure average l;
  847. /* AVERAGE(L) compute the average of the numbers
  848. in list L. Returns 0 if there are none. */
  849. for each x in l
  850. with sm, cnt
  851. initially sm := cnt := 0
  852. when numberp x
  853. do << sm := sm + x; cnt := cnt + 1 >>
  854. returns if cnt > 0 then sm / cnt else 0;
  855. average
  856. if average '(a 12 34) = 23 then
  857. "Test 1 average OK"
  858. else error(0, "Test 1 average fails");
  859. "Test 1 average OK"
  860. if average '(a b c) = 0 then
  861. "Test 2 average OK"
  862. else error(0, "Test 2 average fails");
  863. "Test 2 average OK"
  864. if average '(a b c 5 6) = 5 then
  865. "Test 3 average OK"
  866. else error(0, "Test 3 average fails");
  867. "Test 3 average OK"
  868. if average '(a b c 5 6.0) = 5.5 then
  869. "Test 4 average OK"
  870. else error(0, "Test 4 average fails");
  871. "Test 4 average OK"
  872. %------------------------- Exercise #9 -------------------------
  873. expr procedure boundingbox L;
  874. /* BOUNDINGBOX(L) returns a list of
  875. (min X, max X, min Y, max Y)
  876. for the list L of dotted-pairs (x . y). */
  877. { for each x in L minimize car x,
  878. for each x in L maximize car x,
  879. for each y in L minimize cdr y,
  880. for each y in L maximize cdr y};
  881. boundingbox
  882. if boundingbox '((0 . 1) (4 . 5)) = '(0 4 1 5)
  883. then "Test 1 boundingbox OK"
  884. else error(0, "Test 1 boundingbox fails");
  885. "Test 1 boundingbox OK"
  886. if boundingbox nil = '(0 0 0 0)
  887. then "Test 2 boundingbox OK"
  888. else error(0, "Test 2 boundingbox fails");
  889. "Test 2 boundingbox OK"
  890. if boundingbox '((-5 . 3.4) (3.3 . 2.3) (1.2 . 33)
  891. (-5 . -8) (22.11 . 3.14) (2 . 3)) = '(-5 22.11 -8 33)
  892. then "Test 3 boundingbox OK"
  893. else error(0, "Test 3 boundingbox fails");
  894. "Test 3 boundingbox OK"
  895. %------------------------- Exercise #10 -------------------------
  896. expr procedure maxlists(a, b);
  897. /* MAXLISTS(A, B) -- Build a list such that for each pair
  898. of elements in lists A and B the new list has the largest
  899. element. */
  900. for each ae in a
  901. each be in b
  902. collect max(ae, be);
  903. maxlists
  904. if maxlists('(3 1.2), '(44.22 0.9 1.3)) = '(44.22 1.2)
  905. then "Test 1 maxlists OK"
  906. else error(0, "Test 1 maxlists fails");
  907. "Test 1 maxlists OK"
  908. if maxlists(nil, '(44.22 0.9 1.3)) = nil
  909. then "Test 2 maxlists OK"
  910. else error(0, "Test 2 maxlists fails");
  911. "Test 2 maxlists OK"
  912. if maxlists('(44.22 0.9 1.3), nil) = nil
  913. then "Test 3 maxlists OK"
  914. else error(0, "Test 3 maxlists fails");
  915. "Test 3 maxlists OK"
  916. if maxlists('(1.0 1.2 3.4), '(1 1)) = '(1.0 1.2)
  917. then "Test 4 maxlists OK"
  918. else error(0, "Test 4 maxlists fails");
  919. "Test 4 maxlists OK"
  920. %------------------------- Exercise #11 -------------------------
  921. expr procedure numberedlist l;
  922. /* NUMBEREDLIST(L) -- returns an a-list with the CAR being
  923. elements of L and CDR, the position in the list of the
  924. element starting with 0. */
  925. for i:=0:length l
  926. each e in l
  927. collect e . i;
  928. numberedlist
  929. if numberedlist nil = nil
  930. then "Test 1 numberedlist is OK"
  931. else error(0, "Test 1 numberedlist fails");
  932. "Test 1 numberedlist is OK"
  933. if numberedlist '(a) = '((a . 0))
  934. then "Test 2 numberedlist is OK"
  935. else error(0, "Test 2 numberedlist fails");
  936. "Test 2 numberedlist is OK"
  937. if numberedlist '(a b c) = '((a . 0) (b . 1) (c . 2))
  938. then "Test 2 numberedlist is OK"
  939. else error(0, "Test 2 numberedlist fails");
  940. "Test 2 numberedlist is OK"
  941. %------------------------- Exercise #12 -------------------------
  942. expr procedure reduce x;
  943. /* REDUCE(X) -- X is a list of things some of which are
  944. encapsulated as (!! . y) and returns x. Destructively
  945. replace these elements with just y. */
  946. for each v on x
  947. when eqcar(car v, '!!)
  948. do car v := cdar v
  949. returns x;
  950. reduce
  951. global '(x11);
  952. nil
  953. x11 := '((!! . a) (b c) (d (!! . 34)));
  954. ((!! . a) (b c) (d (!! . 34)))
  955. if reduce x11 = '(a (b c) (d (!! . 34)))
  956. then "Test 1 reduce OK"
  957. else error(0, "Test 1 reduce fails");
  958. "Test 1 reduce OK"
  959. if x11 = '(a (b c) (d (!! . 34)))
  960. then "Test 2 reduce OK"
  961. else error(0, "Test 2 reduce fails");
  962. "Test 2 reduce OK"
  963. % ##### Further Procedure Tests #####
  964. %------------------------- Exercise #1 -------------------------
  965. expr procedure removeflags x;
  966. /* REMOVEFLAGS(X) -- Scan list x replacing each top level
  967. occurrence of (!! . x) with x (whatever x is) and return
  968. the list. Replacement is destructive. */
  969. while x and eqcar(car x, '!!)
  970. with v
  971. initially v := x
  972. do << print x; car x := cdar x; print x; x := cdr x >>
  973. returns v;
  974. removeflags
  975. xxx := '((!!. a) (!! . b) c (!! . d));
  976. ((!! . a) (!! . b) c (!! . d))
  977. if removeflags xxx = '(a b c (!! . d))
  978. then "Test 1 removeflags OK"
  979. else error(0, "Test 1 removeflags fails");
  980. ((!! . a) (!! . b) c (!! . d))
  981. (a (!! . b) c (!! . d))
  982. ((!! . b) c (!! . d))
  983. (b c (!! . d))
  984. "Test 1 removeflags OK"
  985. if xxx = '(a b c (!! . d))
  986. then "Test 2 removeflags OK"
  987. else error(0, "Test 2 removeflags fails");
  988. "Test 2 removeflags OK"
  989. %------------------------- Exercise #2 -------------------------
  990. expr procedure read2char c;
  991. /* READ2CHAR(C) -- Read characters to C and return the
  992. list including C. Terminates at end of file. */
  993. repeat l := (ch := readch()) . l
  994. with ch, l
  995. until ch eq c or ch eq !$EOF!$
  996. returns reversip l;
  997. read2char
  998. if read2char '!* = {!$EOL!$, 'A, 'B, 'C, '!*}
  999. then "Test 1 read2char OK"
  1000. else error(0, "Test 1 read2char fails");
  1001. ABC*
  1002. "Test 1 read2char OK"
  1003. %------------------------- Exercise #3 -------------------------
  1004. expr procedure skipblanks l;
  1005. /* SKIPBLANKS(L) - Returns L with leading blanks
  1006. removed. */
  1007. while l and eqcar(l, '! )
  1008. do l := cdr l
  1009. returns l;
  1010. skipblanks
  1011. if skipblanks '(! ! ! a b) neq '(a b)
  1012. then error(0, "Skipblanks fails test #1");
  1013. nil
  1014. if skipblanks nil
  1015. then error(0, "Skipblanks fails test #2");
  1016. nil
  1017. if skipblanks '(! ! ! )
  1018. then error(0, "Skipblanks fails test #3");
  1019. nil
  1020. if skipblanks '(! ! a b ! ) neq '(a b ! )
  1021. then error(0, "Skipblanks fails test #4");
  1022. nil
  1023. %------------------------- Exercise #4 -------------------------
  1024. expr procedure ntoken l;
  1025. /* NTOKEN(L) - Scan over blanks in l. Then collect
  1026. and return all characters up to the next blank
  1027. returning a dotted-pair of (token . rest of L) or
  1028. NIL if none is found. */
  1029. while l and eqcar(l, '! ) do l := cdr l
  1030. returns
  1031. if l then
  1032. while l and not eqcar(l, '! )
  1033. with tok
  1034. do << tok := car l . tok;
  1035. l := cdr l >>
  1036. returns (reversip tok . l);
  1037. ntoken
  1038. if ntoken '(! ! a b ! ) neq '((a b) . (! ))
  1039. then error(0, "ntoken fails test #1");
  1040. nil
  1041. if ntoken nil then error(0, "ntoken fails test #2");
  1042. nil
  1043. if ntoken '(! ! ! ) then error(0, "ntoken fails test #3");
  1044. nil
  1045. if ntoken '(! ! a b) neq '((a b) . nil)
  1046. then error(0, "ntoken fails test #4");
  1047. nil
  1048. % ##### Block Statement Exercises #####
  1049. %------------------------- Exercise #1 -------------------------
  1050. expr procedure r2nums;
  1051. /* R2NUMS() -- Read 2 numbers and return as a list. */
  1052. begin scalar n1;
  1053. n1 := read();
  1054. return {n1, read()}
  1055. end;
  1056. r2nums
  1057. if r2nums() = '(2 3)
  1058. then "Test 1 r2nums OK"
  1059. else error(0, "Test 1 r2nums failed");
  1060. 2 3
  1061. "Test 1 r2nums OK"
  1062. %------------------------- Exercise #2 -------------------------
  1063. expr procedure readcoordinate;
  1064. /* READCOORDINATE() -- Read a coordinate and return
  1065. it in radians. If prefixed with @, convert from
  1066. degrees. If a list convert from degrees minutes
  1067. seconds. */
  1068. begin scalar x;
  1069. return
  1070. (if (x := read()) eq '!@ then read() / 57.2957795130823208767981
  1071. else if pairp x then
  1072. (car x + cadr x / 60.0 + caddr x / 3600.0)
  1073. / 57.2957795130823208767981
  1074. else x)
  1075. end;
  1076. readcoordinate
  1077. fluid '(val);
  1078. nil
  1079. val := readcoordinate();
  1080. @ 57.29577
  1081. 0.99999983396539
  1082. if val < 1.000001 AND val > 0.999999
  1083. then "Test 1 readcoordinate OK"
  1084. else error(0, "Test 1 readcoordinate failed");
  1085. "Test 1 readcoordinate OK"
  1086. % This fails with poor arithmetic.
  1087. val := readcoordinate();
  1088. (57 17 44.772)
  1089. 0.99999983396539
  1090. if val < 1.000001 AND val > 0.999999
  1091. then "Test 2 readcoordinate OK"
  1092. else error(0, "Test 2 readcoordinate failed");
  1093. "Test 2 readcoordinate OK"
  1094. unfluid '(val);
  1095. nil
  1096. if readcoordinate() = 1.0
  1097. then "Test 3 readcoordinate OK"
  1098. else error(0, "Test 3 readcoordinate failed");
  1099. 1.0
  1100. "Test 3 readcoordinate OK"
  1101. %------------------------- Exercise #3 -------------------------
  1102. expr procedure delallnils l;
  1103. /* DELALLNILS(L) - destructively remove all NIL's from
  1104. list L. The resulting value is always EQ to L. */
  1105. begin scalar p, prev;
  1106. p := l;
  1107. loop: if null p then return l;
  1108. if null car p then
  1109. if null cdr p then
  1110. if null prev then return nil
  1111. else << cdr prev := nil;
  1112. return l >>
  1113. else << car p := cadr p;
  1114. cdr p := cddr p;
  1115. go to loop >>;
  1116. prev := p;
  1117. p := cdr p;
  1118. go to loop
  1119. end;
  1120. delallnils
  1121. fluid '(xxx yyy);
  1122. nil
  1123. % New - added to aid CSL.
  1124. xxx := '(a b c nil d);
  1125. (a b c nil d)
  1126. yyy := delallnils xxx;
  1127. (a b c d)
  1128. if yyy = '(a b c d) and yyy eq xxx
  1129. then "Test 1 dellallnils OK"
  1130. else error(0, "Test 1 delallnils Fails!");
  1131. "Test 1 dellallnils OK"
  1132. xxx := '(a nil b nil c nil d);
  1133. (a nil b nil c nil d)
  1134. yyy := delallnils xxx;
  1135. (a b c d)
  1136. if yyy = '(a b c d) and yyy eq xxx
  1137. then "Test 2 dellallnils OK"
  1138. else error(0, "Test 2 delallnils Fails!");
  1139. "Test 2 dellallnils OK"
  1140. xxx := '(a nil b nil c nil d nil);
  1141. (a nil b nil c nil d nil)
  1142. yyy := delallnils xxx;
  1143. (a b c d)
  1144. if yyy = '(a b c d) and yyy eq xxx
  1145. then "Test 3 dellallnils OK"
  1146. else error(0, "Test 3 delallnils Fails!");
  1147. "Test 3 dellallnils OK"
  1148. xxx := '(a nil nil nil nil b c d);
  1149. (a nil nil nil nil b c d)
  1150. yyy := delallnils xxx;
  1151. (a b c d)
  1152. if yyy = '(a b c d) and yyy eq xxx
  1153. then "Test 4 dellallnils OK"
  1154. else error(0, "Test 4 delallnils Fails!");
  1155. "Test 4 dellallnils OK"
  1156. xxx := '(nil a b c d);
  1157. (nil a b c d)
  1158. yyy := delallnils xxx;
  1159. (a b c d)
  1160. if yyy = '(a b c d) and yyy eq xxx
  1161. then "Test 5 dellallnils OK"
  1162. else error(0, "Test 5 delallnils Fails!");
  1163. "Test 5 dellallnils OK"
  1164. xxx := '(nil nil nil a b c d);
  1165. (nil nil nil a b c d)
  1166. yyy := delallnils xxx;
  1167. (a b c d)
  1168. if yyy = '(a b c d) and yyy eq xxx
  1169. then "Test 6 dellallnils OK"
  1170. else error(0, "Test 6 delallnils Fails!");
  1171. "Test 6 dellallnils OK"
  1172. xxx := '(a b c d nil nil nil);
  1173. (a b c d nil nil nil)
  1174. yyy := delallnils xxx;
  1175. (a b c d)
  1176. if yyy = '(a b c d) and yyy eq xxx
  1177. then "Test 7 dellallnils OK"
  1178. else error(0, "Test 7 delallnils Fails!");
  1179. "Test 7 dellallnils OK"
  1180. %------------------------- Exercise 4 -------------------------
  1181. expr procedure dprin1 x;
  1182. /* DPRIN1(X) - Print X in dotted-pair notation (to
  1183. all levels). Returns X as its value. */
  1184. if vectorp x then
  1185. << prin2 "[";
  1186. for i:=0:upbv x
  1187. do << dprin1 x[i];
  1188. if i < upbv x then prin2 " " >>;
  1189. prin2 "]";
  1190. x >>
  1191. else if atom x then prin1 x
  1192. else << prin2 "(";
  1193. dprin1 car x;
  1194. prin2 " . ";
  1195. dprin1 cdr x;
  1196. prin2 ")";
  1197. x >>;
  1198. dprin1
  1199. % The test is hard to make because we're doing output.
  1200. % Verify the results by hand and make sure it returns the
  1201. % argument.
  1202. dprin1 nil;
  1203. nil
  1204. nil
  1205. dprin1 '(a . b);
  1206. (a . b)
  1207. (a . b)
  1208. dprin1 '(a 1 "foo");
  1209. (a . (1 . ("foo" . nil)))
  1210. (a 1 "foo")
  1211. dprin1 '(((a)));
  1212. (((a . nil) . nil) . nil)
  1213. (((a)))
  1214. << x := mkvect 2; x[0] := 'a; x[1] := '(b c); x[2] := 34; >>;
  1215. nil
  1216. dprin1 {'(b c), x, 34};
  1217. ((b . (c . nil)) . ([a (b . (c . nil)) 34] . (34 . nil)))
  1218. ((b c) [a (b c) 34] 34)
  1219. % ##### Property List Exercises #####
  1220. %---------------------------- Exercise #1 ------------------------------
  1221. global '(stack!*);
  1222. nil
  1223. expr procedure pexecute l;
  1224. /* PEXECUTE(L) - L is a stack language. Constants are
  1225. placed on the global stack!*, id's mean a function
  1226. call to a function under the STACKFN property of the
  1227. function name. Other values are placed on the stack
  1228. without evaluation. */
  1229. if null l then nil
  1230. else if constantp car l then
  1231. << stack!* := car l . stack!*;
  1232. pexecute cdr l >>
  1233. else if idp car l then
  1234. if get(car l, 'STACKFN) then
  1235. << apply(get(car l, 'STACKFN), nil);
  1236. pexecute cdr l >>
  1237. else error(0, {car l, "undefined function"})
  1238. else << stack!* := car l . stack!*;
  1239. pexecute cdr l >>;
  1240. pexecute
  1241. expr procedure pdiff;
  1242. /* PADD1() - Subtract the 2nd stack elt from the
  1243. first and replace top two entries with result. */
  1244. stack!* := (cadr stack!* - car stack!*) . cddr stack!*;
  1245. pdiff
  1246. put('!-, 'STACKFN, 'pdiff);
  1247. pdiff
  1248. expr procedure pplus2;
  1249. /* PPLUS2() - Pop and add the top two numbers
  1250. on the stack and push the result. */
  1251. stack!* := (car stack!* + cadr stack!*) . cddr stack!*;
  1252. pplus2
  1253. put('!+, 'STACKFN, 'pplus2);
  1254. pplus2
  1255. expr procedure pprint;
  1256. /* PPRINT() - Print the top stack element. */
  1257. print car stack!*;
  1258. pprint
  1259. put('PRINT, 'STACKFN, 'pprint);
  1260. pprint
  1261. pexecute '(3 4 !+);
  1262. nil
  1263. if stack!* neq '(7) then error(0, "PEXECUTE test #1 fails");
  1264. nil
  1265. stack!* := nil;
  1266. nil
  1267. pexecute '(5 3 !- 2 4 !+ !+);
  1268. nil
  1269. if stack!* neq '(8) then error(0, "PEXECUTE test #2 fails");
  1270. nil
  1271. %---------------------------- Exercise #2 ------------------------------
  1272. expr procedure pexecute l;
  1273. /* PEXECUTE(L) - L is a stack language. Constants are
  1274. placed on the global stack!*, id's mean a function
  1275. call to a function under the STACKFN property of the
  1276. function name. Other values are placed on the stack
  1277. without evaluation. */
  1278. if null l then nil
  1279. else if constantp car l then
  1280. << stack!* := car l . stack!*;
  1281. pexecute cdr l >>
  1282. else if idp car l then
  1283. if eqcar(l, 'QUOTE) then
  1284. << stack!* := cadr l . stack!*;
  1285. pexecute cddr l >>
  1286. else if flagp(car l, 'STACKVAR) then
  1287. << stack!* := get(car l, 'STACKVAL) . stack!*;
  1288. pexecute cdr l >>
  1289. else if get(car l, 'STACKFN) then
  1290. << apply(get(car l, 'STACKFN), nil);
  1291. pexecute cdr l >>
  1292. else error(0, {car l, "undefined function"})
  1293. else << stack!* := car l . stack!*;
  1294. pexecute cdr l >>;
  1295. +++ pexecute redefined
  1296. pexecute
  1297. expr procedure pset;
  1298. /* PSET() - Put the second value on the stack under
  1299. the STACKVAL attribute of the first. Flag the id as
  1300. a STACKVAR for later use. Pop the top stack
  1301. element. */
  1302. << put(car stack!*, 'STACKVAL, cadr stack!*);
  1303. flag({car stack!*}, 'STACKVAR);
  1304. stack!* := cdr stack!* >>;
  1305. pset
  1306. put('SET, 'STACKFN, 'pset);
  1307. pset
  1308. stack!* := nil;
  1309. nil
  1310. pexecute '(4.5 quote x set 4 !+ x !+ PRINT);
  1311. 13.0
  1312. nil
  1313. if stack!* neq '(13.0) then error(0, "Test 3 PEXECUTE fails");
  1314. nil
  1315. % ##### Records Exercises #####
  1316. %------------------------- Exercise #1 -------------------------
  1317. record qtree /* QTREE is a quad tree node element. */
  1318. with
  1319. node := NIL /* Node name */,
  1320. q1 := NIL /* Child #1 */,
  1321. q2 := NIL /* Child #2 */,
  1322. q3 := NIL /* Child #3 */,
  1323. q4 := NIL /* Child #4 */;
  1324. qtree
  1325. expr procedure qvisit q;
  1326. /* QVISIT(Q) -- Q is a QTREE data structure or NIL as are
  1327. each of its children. Return a preorder visit of each
  1328. node. */
  1329. if null q then nil
  1330. else append({node q},
  1331. append(qvisit q1 q,
  1332. append(qvisit q2 q,
  1333. append(qvisit q3 q, qvisit q4 q))));
  1334. qvisit
  1335. /* A simple quad tree. */
  1336. global '(qdemo);
  1337. nil
  1338. qdemo := qtree(node := 'A,
  1339. q1 := qtree(node := 'B),
  1340. q2 := qtree(node := 'C),
  1341. q3 := qtree(node := 'D,
  1342. q1 := qtree(node := 'E)),
  1343. q4 := qtree(node := 'F));
  1344. [qtree a [qtree b nil nil nil nil] [qtree c nil nil nil nil] [qtree d [qtree e
  1345. nil nil nil nil] nil nil nil] [qtree f nil nil nil nil]]
  1346. if qvisit qdemo = '(A B C D E F)
  1347. then "Test 1 qvisit OK!"
  1348. else error(0, "Test 1 qvisit Fails!");
  1349. "Test 1 qvisit OK!"
  1350. /* The quadtree in the book. */
  1351. global '(qdemo2);
  1352. nil
  1353. qdemo2 := qtree(node := 'A,
  1354. q1 := qtree(node := 'B),
  1355. q2 := qtree(node := 'C),
  1356. q3 := qtree(node := 'D,
  1357. q1 := qtree(node := 'E,
  1358. q2 := qtree(node := 'F)),
  1359. q2 := qtree(node := 'G),
  1360. q3 := qtree(node := 'H),
  1361. q4 := qtree(node := 'I)));
  1362. [qtree a [qtree b nil nil nil nil] [qtree c nil nil nil nil] [qtree d [qtree e
  1363. nil [qtree f nil nil nil nil] nil nil] [qtree g nil nil nil nil] [qtree h nil nil
  1364. nil nil] [qtree i nil nil nil nil]] nil]
  1365. if qvisit qdemo2 = '(A B C D E F G H I)
  1366. then "Test 2 qvisit OK!"
  1367. else error(0, "Test 2 qvisit Fails!");
  1368. "Test 2 qvisit OK!"
  1369. if qvisit nil = NIL
  1370. then "Test 3 qvisit OK!"
  1371. else error(0, "Test 3 qvisit Fails!");
  1372. "Test 3 qvisit OK!"
  1373. %------------------------- Exercise #2 -------------------------
  1374. expr procedure qsearch(q, val, fn);
  1375. /* QSEARCH(Q, VAL, FN) -- Returns the node path from the
  1376. root of the quadtree Q to VAL using FN as an equality
  1377. function whose first argument is from the tree and
  1378. second VAL. */
  1379. if null q then nil
  1380. else if apply(fn, {val, node q}) then {node q}
  1381. else begin scalar v;
  1382. if v := qsearch(q1 q, val, fn) then return node q . v;
  1383. if v := qsearch(q2 q, val, fn) then return node q . v;
  1384. if v := qsearch(q3 q, val, fn) then return node q . v;
  1385. if v := qsearch(q4 q, val, fn) then return node q . v
  1386. end;
  1387. qsearch
  1388. if qsearch(qdemo, 'E, function EQ) = '(A D E)
  1389. then "Test 1 qsearch OK!"
  1390. else error(0, "Test 1 qsearch fails");
  1391. "Test 1 qsearch OK!"
  1392. if qsearch(qdemo, 'XXX, function EQ) = nil
  1393. then "Test 2 qsearch OK!"
  1394. else error(0, "Test 2 qsearch fails");
  1395. "Test 2 qsearch OK!"
  1396. if qsearch(qdemo2, 'F, function EQ) = '(A D E F)
  1397. then "Test 3 qsearch OK!"
  1398. else error(0, "Test 3 qsearch fails");
  1399. "Test 3 qsearch OK!"
  1400. %------------------------- Exercise #3 -------------------------
  1401. record commchain
  1402. /* A COMMCHAIN is an n-ary tree with superior and
  1403. subordinate links. */
  1404. with
  1405. name := NIL /* Name of this node. */,
  1406. superior := NIL /* Pointer to superior node. */,
  1407. subordinates := NIL /* List of subordinates. */;
  1408. commchain
  1409. expr procedure backchain(l, sup);
  1410. /* BACKCHAIN(L, SUP) -- Fill in the SUPERIOR fields of
  1411. each record in the n-ary tree (links in the SUBORDINATES
  1412. field) to the lowest level. SUP is the current
  1413. superior. */
  1414. if null l then nil
  1415. else << superior l := sup;
  1416. for each sb in subordinates l
  1417. do backchain(sb, l) >>;
  1418. backchain
  1419. /* Demo the back chain. */
  1420. global '(cch);
  1421. nil
  1422. cch :=
  1423. commchain(
  1424. name := 'TOP,
  1425. subordinates :=
  1426. {commchain(name := 'LEV1-A),
  1427. commchain(
  1428. name := 'LEV1-B,
  1429. subordinates :=
  1430. {commchain(name := 'LEV2-A),
  1431. commchain(name := 'LEV2-B)}),
  1432. commchain(name := 'LEV1-C)});
  1433. [commchain top nil ([commchain lev1!-a nil nil] [commchain lev1!-b nil ([
  1434. commchain lev2!-a nil nil] [commchain lev2!-b nil nil])] [commchain lev1!-c nil
  1435. nil])]
  1436. % Wrap this up to avoid printing problems.
  1437. << backchain(cch, 'COMMANDER); NIL >>;
  1438. nil
  1439. if superior cch EQ 'COMMANDER
  1440. then "Test 1 backchain OK!"
  1441. else error(0, "Test 1 backchain Fails!");
  1442. "Test 1 backchain OK!"
  1443. if name superior car subordinates cch EQ 'TOP
  1444. then "Test 2 backchain OK!"
  1445. else error(0, "Test 2 backchain Fails!");
  1446. "Test 2 backchain OK!"
  1447. if name superior car subordinates cadr subordinates cch
  1448. eq 'LEV1-B
  1449. then "Test 3 backchain OK!"
  1450. else error(0, "Test 3 backchain Fails!");
  1451. "Test 3 backchain OK!"
  1452. % ##### Local Variable Exercises #####
  1453. %------------------------- Exercise #1 -------------------------
  1454. expr procedure lookup(v, a);
  1455. /* LOOKUP(V, A) -> Look for V in A and signal an error if not present.*/
  1456. (if rv then cdr rv else error(0, {v, "not in association list"}))
  1457. where rv := assoc(v, a);
  1458. lookup
  1459. if lookup('a, '((a . b) (c . d))) = 'b
  1460. then "Test 1 lookup success"
  1461. else error(0, "Test 1 lookup fails");
  1462. "Test 1 lookup success"
  1463. if errorset(quote lookup('f, '((a . b) (c . d))), nil, nil) = 0
  1464. then "Test 2 lookup success"
  1465. else error(0, "Test 2 lookup fails");
  1466. "Test 2 lookup success"
  1467. %------------------------- Exercise #2 -------------------------
  1468. expr procedure quadratic(a, b, c);
  1469. /* QUADRATIC(A, B, C) -- Returns both solutions of the
  1470. quadratic equation A*X^2 + B*X + C */
  1471. {(-B + U) / V, (-B - U) / V}
  1472. where U := SQRT(B^2 - 4*A*C),
  1473. V := 2.0 * A;
  1474. quadratic
  1475. if quadratic(1.0, 2.0, 1.0) = '(-1.0 -1.0)
  1476. then "Test 1 quadratic OK!"
  1477. else error(0, "Test 1 quadratic Fails!");
  1478. "Test 1 quadratic OK!"
  1479. if quadratic(1.0, 0.0, -1.0) = '(1.0 -1.0)
  1480. then "Test 2 quadratic OK!"
  1481. else error(0, "Test 2 quadratic Fails!");
  1482. "Test 2 quadratic OK!"
  1483. %------------------------- Exercise #3 -------------------------
  1484. expr procedure lineintersection(x1, y1,
  1485. x2, y2,
  1486. x3, y3,
  1487. x4, y4);
  1488. /* LINEINTERSECTION(X1,Y1,X2,Y2,X3,Y3,X4,Y4) -
  1489. Computes the intersection of line X1,Y1 ->
  1490. X2,Y2 with X3,Y3 -> X4,Y4 if any. Returns NIL
  1491. if no such intersection. */
  1492. (if zerop denom or zerop d1 or zerop d2 then nil
  1493. else
  1494. ((if p1 < 0 or p1 > d1 or p2 < 0 or p2 > d2
  1495. then nil
  1496. else (x1 + (x2 - x1) * p1 / d1) .
  1497. (y1 + (y2 - y1) * p1 / d1))
  1498. where p1 := num1 / denom,
  1499. p2 := num2 / denom)
  1500. where
  1501. num1 := d1*(x1*y3 - x1*y4 - x3*y1 + x3*y4
  1502. + x4*y1 - x4*y3),
  1503. num2 := d2*(- x1*y2 + x1*y3 + x2*y1 - x2*y3
  1504. - x3*y1 + x3*y2))
  1505. where d1 :=sqrt((x2 - x1)^2 + (y2 - y1)^2),
  1506. d2 := sqrt((x4 - x3)^2 + (y4 - y3)^2),
  1507. denom := x1*y3 - x1*y4 - x2*y3 + x2*y4
  1508. - x3*y1 + x3*y2 + x4*y1 - x4*y2;
  1509. lineintersection
  1510. if lineintersection(1, 1, 3, 3, 1, 2, 5, 2) = '(2.0 . 2.0)
  1511. then "Test 1 LINEINTERSECTION success!"
  1512. else error(0, "Test 1 LINEINTERSECTION fails intersect test");
  1513. "Test 1 LINEINTERSECTION success!"
  1514. % intersection at start and end points.
  1515. if lineintersection(1, 1, 2, 2, 1, 1, 1, 0) = '(1.0 . 1.0)
  1516. then "Test 2 LINEINTERSECTION success!"
  1517. else error(0, "Test 2LINEINTERSECTION fails intersect at start test");
  1518. "Test 2 LINEINTERSECTION success!"
  1519. if lineintersection(1, 1, 2, 2, 0, 1, 2, 2) = '(2.0 . 2.0)
  1520. then "Test 3 LINEINTERSECTION success!"
  1521. else error(0,
  1522. "Test 3 LINEINTERSECTION fails intersect at endpoint test");
  1523. "Test 3 LINEINTERSECTION success!"
  1524. if lineintersection(1, 1, 2, 2, 2, 2, 3, 4) = '(2.0 . 2.0)
  1525. then "Test 4 LINEINTERSECTION success!"
  1526. else error(0,
  1527. "Test 4 LINEINTERSECTION fails intersect end - begin point test");
  1528. "Test 4 LINEINTERSECTION success!"
  1529. % Now try no intersection test.
  1530. if null lineintersection(1, 1, 2, 3, 2, 4, 4, 5)
  1531. then "Test 5 LINEINTERSECTION success!"
  1532. else error(0,
  1533. "Test 5 LINEINTERSECTION fails quadrant 1 no intersection");
  1534. "Test 5 LINEINTERSECTION success!"
  1535. if null lineintersection(1, 1, 2, 2, 1.75, 1.5, 5, 1.75)
  1536. then "Test 6 LINEINTERSECTION success!"
  1537. else error(0,
  1538. "Test 6 LINEINTERSECTION fails quadrant 2 no intersection");
  1539. "Test 6 LINEINTERSECTION success!"
  1540. %------------------------- Exercise #4 -------------------------
  1541. expr procedure stdev x;
  1542. /* STDEV(X) - compute the standard deviation of the
  1543. numbers in list X. */
  1544. if null x then 0
  1545. else (sqrt((for each v in x sum (v - avg)^2) / n)
  1546. where avg := (for each v in x sum v) / n)
  1547. where n := length x;
  1548. stdev
  1549. if stdev '(3.0 3.0 3.0) neq 0.0 then
  1550. error(0, "Test 1 STDEV fails");
  1551. nil
  1552. % ##### Array Exercises #####
  1553. %------------------------- Exercise #1 -------------------------
  1554. expr procedure vaverage v;
  1555. /* VAVERAGE(V) -- compute the average of all numeric
  1556. elements of the vector v. */
  1557. (if cnt > 0 then
  1558. ((for i:=0:upbv v when numberp v[i] sum v[i]) / float cnt)
  1559. else 0.0)
  1560. where cnt := for i:=0:upbv v count numberp v[i];
  1561. vaverage
  1562. if vaverage array(1,2,3) = 2.0
  1563. then "Test 1 vaverage is OK"
  1564. else error(0, "Test 1 vaverage fails");
  1565. "Test 1 vaverage is OK"
  1566. if vaverage array(3, 'a, 3, 6.0, 'f) = 4.0
  1567. then "Test 2 vaverage is OK"
  1568. else error(0, "Test 2 vaverage fails");
  1569. "Test 2 vaverage is OK"
  1570. if vaverage array('a, 'b) = 0.0
  1571. then "Test 3 vaverage is OK"
  1572. else error(0, "Test 3 vaverage fails");
  1573. "Test 3 vaverage is OK"
  1574. %------------------------- Exercise #2 -------------------------
  1575. expr procedure MAPPEND(a, b);
  1576. /* MAPPEND(A, B) -- Appends array B to array A and
  1577. returns a new array with both. */
  1578. begin scalar c, ua;
  1579. c := mkvect((ua := 1 + upbv a) + upbv b);
  1580. for i:=0:upbv a do c[i] := a[i];
  1581. for i:=0:upbv b do c[i + ua] := b[i];
  1582. return c
  1583. end;
  1584. +++ mappend redefined
  1585. mappend
  1586. global '(a1 a2);
  1587. nil
  1588. a1 := array(1, 2, 3);
  1589. [1 2 3]
  1590. a2 := array(3, 4, 5, 6);
  1591. [3 4 5 6]
  1592. if mappend(a1, a2) = array(1,2,3,3,4,5,6)
  1593. then "Test 1 MAPPEND is OK"
  1594. else error(0, "Test 1 MAPPEND fails");
  1595. "Test 1 MAPPEND is OK"
  1596. if mappend(mkvect 0, mkvect 0) = mkvect 1
  1597. then "Test 2 MAPPEND is OK"
  1598. else error(0, "Test 2 MAPPEND fails");
  1599. "Test 2 MAPPEND is OK"
  1600. %------------------------- Exercise #3 -------------------------
  1601. expr procedure indx(a, v);
  1602. /* INDX(A, V) -- returns index of A in V using EQ test,
  1603. otherwise NIL. */
  1604. for i:=0:upbv v
  1605. until a eq v[i]
  1606. returns if i <= upbv v then i
  1607. if indx('a, array(1, 2, 'a, 34)) = 2
  1608. then "Test 1 indx OK"
  1609. else error(0, "Test 1 indx fails");
  1610. indx
  1611. if null indx('a, array(1, 2, 3, 4))
  1612. then "Test 2 indx OK"
  1613. else error(0, "Test 2 indx fails");
  1614. "Test 2 indx OK"
  1615. %------------------------- Exercise #4 -------------------------
  1616. expr procedure mpy4x4(a, b);
  1617. /* MPY4X4(A, B) -- Create a new 4x4 matrix and return with
  1618. the product of A and B in it. */
  1619. for row:=0:3
  1620. with c, s
  1621. initially c := mkarray(3,3)
  1622. do << for col := 0:3 do
  1623. do c[row,col] :=
  1624. for p := 0:3 sum a[row,p] * b[p,col] >>
  1625. returns c;
  1626. mpy4x4
  1627. expr procedure translate4x4(x, y, z);
  1628. /* TRANSLATE4X4(X, Y, Z) -- Generate and return a
  1629. 4x4 matrix to translate X, Y, Z. */
  1630. array(array(1.0, 0.0, 0.0, 0.0),
  1631. array(0.0, 1.0, 0.0, 0.0),
  1632. array(0.0, 0.0, 1.0, 0.0),
  1633. array(x, y, z, 1.0));
  1634. translate4x4
  1635. expr procedure rotatex4x4 th;
  1636. /* ROTATEX4X4(TH) -- Generate a 4x4 rotation matrix about
  1637. the X axis, TH radians. */
  1638. array(array(1.0, 0.0, 0.0, 0.0),
  1639. array(0.0, cos th, -sin th, 0.0),
  1640. array(0.0, sin th, cos th, 0.0),
  1641. array(0.0, 0.0, 0.0, 1.0));
  1642. rotatex4x4
  1643. expr procedure mappoint(x, y, z, m);
  1644. /* MAPPOINT(X, Y, Z, M) -- Returns the transformed point
  1645. X, Y, Z by the 4x4 matrix M. */
  1646. {x*m[0,0] + y*m[1,0] + z*m[2,0] + m[3,0],
  1647. x*m[0,1] + y*m[1,1] + z*m[2,1] + m[3,1],
  1648. x*m[0,2] + y*m[1,2] + z*m[2,2] + m[3,2]};
  1649. mappoint
  1650. /* tmat is test matrix to rotate about x. In our tests we
  1651. have to construct the resulting numbers on the fly
  1652. because when input, they aren't the same for EQUAL. */
  1653. global '(tmat);
  1654. nil
  1655. tmat := rotatex4x4(45.0 / 57.29577);
  1656. [[1.0 0.0e+000 0.0e+000 0.0e+000] [0.0e+000 0.70710668897748 -0.7071068733956
  1657. 0.0e+000] [0.0e+000 0.7071068733956 0.70710668897748 0.0e+000] [0.0e+000 0.0e+000
  1658. 0.0e+000 1.0]]
  1659. if mappoint(0.0, 0.0, 0.0, tmat) = '(0.0 0.0 0.0)
  1660. then "Test 1 4x4 OK"
  1661. else error(0, "Test 1 4x4 failed");
  1662. "Test 1 4x4 OK"
  1663. if mappoint(1.0, 0.0, 0.0, tmat) = '(1.0 0.0 0.0)
  1664. then "Test 2 4x4 OK"
  1665. else error(0, "Test 2 4x4 failed");
  1666. "Test 2 4x4 OK"
  1667. if mappoint(0.0, 1.0, 0.0, tmat) =
  1668. {0.0, cos(45.0 / 57.29577), - sin(45.0 / 57.29577)}
  1669. then "Test 3 4x4 OK"
  1670. else error(0, "Test 3 4x4 failed");
  1671. "Test 3 4x4 OK"
  1672. if mappoint(1.0, 1.0, 0.0, tmat) =
  1673. {1.0, cos(45.0 / 57.29577), - sin(45.0 / 57.29577)}
  1674. then "Test 4 4x4 OK"
  1675. else error(0, "Test 4 4x4 failed");
  1676. "Test 4 4x4 OK"
  1677. if mappoint(0.0, 0.0, 1.0, tmat) =
  1678. {0.0, sin(45.0 / 57.29577), cos(45.0 / 57.29577)}
  1679. then "Test 5 4x4 OK"
  1680. else error(0, "Test 5 4x4 failed");
  1681. "Test 5 4x4 OK"
  1682. if mappoint(1.0, 0.0, 1.0, tmat) =
  1683. {1.0, sin(45.0 / 57.29577), cos(45.0 / 57.29577)}
  1684. then "Test 6 4x4 OK"
  1685. else error(0, "Test 6 4x4 failed");
  1686. "Test 6 4x4 OK"
  1687. if mappoint(0.0, 1.0, 1.0, tmat) =
  1688. {0.0, cos(45.0 / 57.29577) + sin(45.0 / 57.29577),
  1689. cos(45.0 / 57.29577) - sin(45.0 / 57.29577)}
  1690. then "Test 7 4x4 OK"
  1691. else error(0, "Test 7 4x4 failed");
  1692. "Test 7 4x4 OK"
  1693. if mappoint(1.0, 1.0, 1.0, tmat) =
  1694. {1.0, cos(45.0 / 57.29577) + sin(45.0 / 57.29577),
  1695. cos(45.0 / 57.29577) - sin(45.0 / 57.29577)}
  1696. then "Test 8 4x4 OK"
  1697. else error(0, "Test 8 4x4 failed");
  1698. "Test 8 4x4 OK"
  1699. /* Now try the multiplication routine. */
  1700. tmat := mpy4x4(rotatex4x4(45.0 / 57.29577),
  1701. translate4x4(1.0, 2.0, 3.0));
  1702. [[1.0 0.0e+000 0.0e+000 0.0e+000] [0.0e+000 0.70710668897748 -0.7071068733956
  1703. 0.0e+000] [0.0e+000 0.7071068733956 0.70710668897748 0.0e+000] [1.0 2.0 3.0 1.0]
  1704. ]
  1705. if mappoint(0.0, 0.0, 0.0, tmat) = '(1.0 2.0 3.0)
  1706. then "Test 9 4x4 OK"
  1707. else error(0, "Test 9 4x4 failed");
  1708. "Test 9 4x4 OK"
  1709. if mappoint(0.0, 0.0, 1.0, tmat) =
  1710. {1.0, 2.0 + sin(45.0 / 57.29577),
  1711. 3.0 + cos(45.0 / 57.29577)}
  1712. then "Test 10 4x4 OK"
  1713. else error(0, "Test 10 4x4 failed");
  1714. "Test 10 4x4 OK"
  1715. %------------------------- Exercise 4 -------------------------
  1716. expr procedure ltident n;
  1717. /* LTIDENT(N) -- Create and return a lower triangular,
  1718. square, identity matrix with N+1 rows. */
  1719. for i:=0:n
  1720. with a
  1721. initially a := mkvect n
  1722. do << a[i] := mkvect i;
  1723. for j:=0:i - 1 do a[i,j] := 0.0;
  1724. a[i,i] := 1.0 >>
  1725. returns a;
  1726. ltident
  1727. expr procedure ltmpy(a, b);
  1728. /* LTMPY(A, B) -- Compute the product of two square,
  1729. lower triangular matrices of the same size and return.
  1730. Note that the product is also lower triangular. */
  1731. (for i:=0:rows
  1732. with c
  1733. initially c := mkvect rows
  1734. do << c[i] := mkvect i;
  1735. for j:=0:i do
  1736. c[i,j] := for k:=j:i sum a[i,k] * b[k,j] >>
  1737. returns c)
  1738. where rows := upbv a;
  1739. ltmpy
  1740. if ltident 2 = array(array(1.0),
  1741. array(0.0, 1.0),
  1742. array(0.0, 0.0, 1.0))
  1743. then "Test 1 ltident OK"
  1744. else "Test 1 ltident fails";
  1745. "Test 1 ltident OK"
  1746. if ltident 0 = array(array(1.0))
  1747. then "Test 2 ltident OK"
  1748. else "Test 2 ltident fails";
  1749. "Test 2 ltident OK"
  1750. if ltmpy(ltident 2, ltident 2) = ltident 2
  1751. then "Test 3 ltident OK"
  1752. else "Test 3 ltident fails";
  1753. "Test 3 ltident OK"
  1754. if ltmpy(array(array(1.0),
  1755. array(1.0, 2.0),
  1756. array(1.0, 2.0, 3.0)),
  1757. array(array(1.0),
  1758. array(1.0, 2.0),
  1759. array(1.0, 2.0, 3.0))) =
  1760. array(array(1.0),
  1761. array(3.0, 4.0),
  1762. array(6.0, 10.0, 9.0))
  1763. then "Test 4 ltmpy OK"
  1764. else error(0, "Test 4 ltmpy fails");
  1765. "Test 4 ltmpy OK"
  1766. if ltmpy(array(array(1.2),
  1767. array(3.4, 5.0),
  1768. array(1.0,-2.3,-1.3)), ltident 2)
  1769. = array(array(1.2),
  1770. array(3.4, 5.0),
  1771. array(1.0, -2.3, -1.3))
  1772. then "Test 5 ltmpy OK"
  1773. else error(0, "Test 5 ltmpy fails");
  1774. "Test 5 ltmpy OK"
  1775. %------------------------- Exercise #5 -------------------------
  1776. expr procedure coerce(a, b, pth, cmat);
  1777. /* COERCE(A,B,PTH,CMAT) -- return a list of functions
  1778. to coerce type A (an index into CMAT) into type B. PTH
  1779. is NIL to start and CMAT the coercion table arranged
  1780. with "from" type as rows, "to" type as columns. */
  1781. if cmat[a,b] then cmat[a,b] . pth
  1782. else
  1783. for j:=0:upbv cmat[a]
  1784. with cp
  1785. until j neq a and cmat[a,j] and
  1786. not (cmat[a,j] memq pth) and
  1787. not(cmat[j,a] memq pth) and
  1788. (cp := coerce(j, b, cmat[a,j] . pth, cmat))
  1789. returns cp;
  1790. coerce
  1791. /* Create the coercion array. Here int=0, string=1,
  1792. float=2, complex=3, and gaussian=4 */
  1793. global '(cpath);
  1794. nil
  1795. cpath :=
  1796. array(array('ident, 'int2str, 'float, nil, nil),
  1797. array('str2int, 'ident, 'str2flt, nil, nil),
  1798. array('fix, 'flt2str, 'ident, 'flt2cplx,nil),
  1799. array(nil, nil, nil, 'ident, 'cfix),
  1800. array(nil, nil, nil, 'cfloat, 'ident));
  1801. [[ident int2str float nil nil] [str2int ident str2flt nil nil] [fix flt2str ident
  1802. flt2cplx nil] [nil nil nil ident cfix] [nil nil nil cfloat ident]]
  1803. % Coerce int to complex.
  1804. if coerce(0, 3, nil, cpath) = '(FLT2CPLX STR2FLT INT2STR)
  1805. then "Test 1 coerce OK"
  1806. else error(0, "Test 1 coerce fails");
  1807. "Test 1 coerce OK"
  1808. % Coerce Complex into int.
  1809. if coerce(3, 0, nil, cpath) = NIL
  1810. then "Test 2 coerce OK"
  1811. else error(0, "Test 2 coerce fails");
  1812. "Test 2 coerce OK"
  1813. % Coerce int into gaussian.
  1814. if coerce(0, 4, nil, cpath) =
  1815. '(CFIX FLT2CPLX STR2FLT INT2STR)
  1816. then "Test 3 coerce OK"
  1817. else error(0, "Test 3 coerce fails");
  1818. "Test 3 coerce OK"
  1819. %------------------------- Exercise #6 -------------------------
  1820. expr procedure cellvon(a, b, fn);
  1821. /* CELLVON(A, B, FN) -- Compute the next generation of the
  1822. cellular matrix A and place it into B. Use the VonNeumann
  1823. neighborhood and the function FN to compute the next
  1824. generation. The space edges are wrapped into a torus*/
  1825. for r:=0:rows
  1826. with rows, cols
  1827. initially << rows := upbv a; cols := upbv a[1] >>
  1828. do for c:=0:cols
  1829. do b[r,c] := apply(fn,
  1830. {a[r,c],
  1831. a[torus(r + 1, rows), torus(c - 1, cols)],
  1832. a[torus(r + 1, rows), c],
  1833. a[torus(r + 1, rows), torus(c + 1, cols)],
  1834. a[r, torus(c + 1, cols)],
  1835. a[torus(r - 1, rows), torus(c + 1, cols)],
  1836. a[torus(r - 1, rows), c],
  1837. a[torus(r - 1, rows), torus(c - 1, cols)],
  1838. a[r, torus(c - 1, cols)]});
  1839. cellvon
  1840. expr procedure torus(i, v);
  1841. /* TORUS(I, V) -- A positive modulus: if I is less than
  1842. 0, wrap to V, or if it exceeds V, wrap to I. */
  1843. if i < 0 then v
  1844. else if i > v then 0
  1845. else i;
  1846. torus
  1847. expr procedure life(c, n1, n2, n3, n4, n5, n6, n7, n8);
  1848. /* LIFE(C, N1 ... N8) -- Game of life rules. Here C is
  1849. the cell being examined and N1-N8 are the VonNeumann
  1850. neighbor states. */
  1851. (if c = 1 then if cnt = 2 or cnt = 3 then 1 else 0
  1852. else if cnt = 3 then 1 else 0)
  1853. where cnt = n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8;
  1854. life
  1855. /* LIFESTATES contains a vector of states and what
  1856. character to print. */
  1857. global '(LIFESTATES);
  1858. nil
  1859. LIFESTATES := array(" ", "*");
  1860. [" " "*"]
  1861. expr procedure pcell(gen, a, pr);
  1862. /* PCELL(GEN, A) -- Display the state of the GEN generation
  1863. of the cellular matrix A. Display a * for state=1, and
  1864. a blank for state 0. */
  1865. for r:=0:rows
  1866. with rows, cols
  1867. initially << rows := upbv a; cols := upbv a[1];
  1868. terpri(); prin2 "Generation: "; print gen >>
  1869. do << terpri();
  1870. for c:=0:cols do prin2 pr[a[r,c]] >>;
  1871. pcell
  1872. expr procedure rungame(a, n, fn, pr);
  1873. /* RUNGAME(A, N, FN, PR) -- Run through N generations
  1874. starting with the cellular matrix A and using the
  1875. function FNto compute the new generation. Use the array
  1876. PR to display the state. */
  1877. for i:=1:n
  1878. with tmp, b
  1879. initially b := mkarray(upbv a, upbv a[1])
  1880. do << pcell(i, a, pr);
  1881. cellvon(a, b, function life);
  1882. tmp := a; a := b; b := tmp >>;
  1883. *** local variable fn in procedure rungame not used
  1884. rungame
  1885. /* SEED is the seed array with 1's for on state, 0 for
  1886. off. */
  1887. global '(seed);
  1888. nil
  1889. seed := array(
  1890. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1891. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1892. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1893. array(0, 0, 0, 0, 0, 1, 0, 0, 0, 0),
  1894. array(0, 0, 0, 0, 0, 0, 1, 0, 0, 0),
  1895. array(0, 0, 0, 0, 1, 1, 1, 0, 0, 0),
  1896. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1897. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1898. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  1899. array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
  1900. [[0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0
  1901. 0 0 0] [0 0 0 0 0 0 1 0 0 0] [0 0 0 0 1 1 1 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0
  1902. 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0]]
  1903. rungame(seed, 10, function life, LIFESTATES);
  1904. Generation: 1
  1905. *
  1906. *
  1907. ***
  1908. Generation: 2
  1909. * *
  1910. **
  1911. *
  1912. Generation: 3
  1913. *
  1914. * *
  1915. **
  1916. Generation: 4
  1917. *
  1918. **
  1919. **
  1920. Generation: 5
  1921. *
  1922. *
  1923. ***
  1924. Generation: 6
  1925. * *
  1926. **
  1927. *
  1928. Generation: 7
  1929. *
  1930. * *
  1931. **
  1932. Generation: 8
  1933. *
  1934. **
  1935. **
  1936. Generation: 9
  1937. *
  1938. *
  1939. ***
  1940. Generation: 10
  1941. * *
  1942. **
  1943. *
  1944. nil
  1945. %------------------------- Exercise #7 -------------------------
  1946. expr procedure compact heap;
  1947. /* compact(HEAP) -- HEAP is an array of blocks of
  1948. sequentially allocated items. The first entry in each
  1949. block is INUSE, the second the total number of entries
  1950. + 2 (for the header). The remainder are random values.
  1951. Free blocks are the same but instead have the header
  1952. FREE. Returns a compacted structure with a single FREE
  1953. entry at the end with entries changed to *. Returns the
  1954. number of free entries. */
  1955. begin scalar dest, src, last, u;
  1956. last := dest := src := 0;
  1957. loop: if src > upbv heap then
  1958. if src = dest then return 0
  1959. else << heap[dest] := 'FREE;
  1960. heap[dest+1] := src - dest;
  1961. for i:=dest+2:upbv heap do heap[i] := '!*;
  1962. return heap[dest+1] >>;
  1963. if heap[src] eq 'FREE then
  1964. src := heap[src+1] + src
  1965. else << u := heap[src+1] + src - 1;
  1966. for i:=src:u do << heap[dest] := heap[i];
  1967. dest := dest + 1 >>;
  1968. src := u + 1 >>;
  1969. go to loop
  1970. end;
  1971. compact
  1972. /* A simple array to test. */
  1973. global '(H);
  1974. nil
  1975. H := array('INUSE, 3, 0,
  1976. 'FREE, 4, '!*, '!*,
  1977. 'INUSE, 4, 0, 1,
  1978. 'FREE, 3, '!*,
  1979. 'FREE, 5, '!*, '!*, '!*,
  1980. 'INUSE, 5, 0, 1, 2,
  1981. 'INUSE, 5, 3, 4, 5);
  1982. [inuse 3 0 free 4 !* !* inuse 4 0 1 free 3 !* free 5 !* !* !* inuse 5 0 1 2 inuse
  1983. 5 3 4 5]
  1984. if compact H = 12
  1985. then "Test 1 compact OK!"
  1986. else error(0, "Test 1 compact fails!");
  1987. "Test 1 compact OK!"
  1988. if H = array('INUSE, 3, 0, 'INUSE, 4, 0, 1, 'INUSE,
  1989. 5, 0, 1, 2, 'INUSE, 5, 3, 4, 5,
  1990. 'FREE, 12, '!*, '!*, '!*, '!*, '!*, '!*,
  1991. '!*, '!*, '!*, '!*)
  1992. then "Test 2 compact OK!"
  1993. else error(0, "Test 2 compact fails!");
  1994. "Test 2 compact OK!"
  1995. /* Test a completely full one. */
  1996. H := array('INUSE, 3, 0, 'INUSE, 5, 1, 2, 3);
  1997. [inuse 3 0 inuse 5 1 2 3]
  1998. if compact H = 0
  1999. then "Test 3 compact OK!"
  2000. else error(0, "Test 3 compact fails!");
  2001. "Test 3 compact OK!"
  2002. if H = array('INUSE, 3, 0, 'INUSE, 5, 1, 2, 3)
  2003. then "Test 4 compact OK!"
  2004. else error(0, "Test 4 compact fails!");
  2005. "Test 4 compact OK!"
  2006. /* Test a completely empty one. */
  2007. H := array('FREE, 3, '!*, 'FREE, 5, '!*, '!*, '!*);
  2008. [free 3 !* free 5 !* !* !*]
  2009. if compact H = 8
  2010. then "Test 5 compact OK!"
  2011. else error(0, "Test 5 compact fails!");
  2012. "Test 5 compact OK!"
  2013. if H = array('FREE, 8, '!*, '!*, '!*, '!*, '!*, '!*)
  2014. then "Test 6 compact OK!"
  2015. else error(0, "Test 6 compact fails!");
  2016. "Test 6 compact OK!"
  2017. %------------------------- Exercise #8 -------------------------
  2018. expr procedure HISTOGRAM(v, n);
  2019. /* HISTOGRAM(V,N) -- V is an arbitrarily size vector of
  2020. numbers. Compute its an N element histogram over its
  2021. range and return it. */
  2022. begin scalar minv, maxv, h, range;
  2023. minv := maxv := v[0];
  2024. for i:=1:upbv v
  2025. do << if v[i] < minv then minv := v[i];
  2026. if v[i] > maxv then maxv := v[i] >>;
  2027. range := maxv - minv;
  2028. h := mkvect(n - 1);
  2029. for i:=0:n - 1 do h[i] := 0;
  2030. for i:=0:upbv v
  2031. with hn
  2032. do << hn := fix(n * (v[i] - minv) / range);
  2033. if hn = n then hn := hn - 1;
  2034. h[hn] := h[hn] + 1 >>;
  2035. return h
  2036. end;
  2037. histogram
  2038. global '(v1);
  2039. nil
  2040. << v1 := mkvect 100;
  2041. for i:=0:100 do v1[i] := float i >>;
  2042. nil
  2043. if HISTOGRAM(v1, 1) = array(101)
  2044. then "Test 1 HISTOGRAM OK!"
  2045. else error(0, "Test 1 HISTOGRAM Fails!");
  2046. "Test 1 HISTOGRAM OK!"
  2047. if HISTOGRAM(v1, 2) = array(50, 51)
  2048. then "Test 2 HISTOGRAM OK!"
  2049. else error(0, "Test 2 HISTOGRAM Fails!");
  2050. "Test 2 HISTOGRAM OK!"
  2051. if HISTOGRAM(v1, 7) = array(15, 14, 14, 15, 14, 14, 15)
  2052. then "Test 3 HISTOGRAM OK!"
  2053. else error(0, "Test 3 HISTOGRAM Fails!");
  2054. "Test 3 HISTOGRAM OK!"
  2055. %------------------------- Exercise #9 -------------------------
  2056. expr procedure rarray n;
  2057. /* RARRAY(N) - generate an NxN matrix with uniform
  2058. distribution random numbers in the range 0.0 -> 1.0. */
  2059. for x:=0:n
  2060. with a
  2061. initially a := mkarray(n,n)
  2062. returns a
  2063. do for y:=0:n do a[x,y] := random(1000) / 1000.0;
  2064. rarray
  2065. if upbv rarray 4 = 4
  2066. then "Test 1 rarray OK"
  2067. else error(0, "Test 1 rarray fails");
  2068. "Test 1 rarray OK"
  2069. expr procedure addcircle(a, r, xc, yc, v);
  2070. /* ADDCIRCLE(A, R, XC, YC, V) -- Add V to each cell within
  2071. distance R from center point XC, YC and return a new
  2072. matrix with these values. Values always remain in the
  2073. range 0.0 -> 1.0. */
  2074. begin scalar uax, uay, b;
  2075. b := mkarray(uax := upbv a, uay := upbv a[0]);
  2076. for x:=0:uax do
  2077. for y:=0:uay do
  2078. b[x,y] := if sqrt((x - xc)^2 + (y - yc)^2) <= r
  2079. then min(1.0, v + a[x,y]) else a[x,y];
  2080. return b
  2081. end;
  2082. addcircle
  2083. global '(xxx);
  2084. nil
  2085. xxx := array(array(0, 0, 0, 0, 0),
  2086. array(0, 0, 0, 0, 0),
  2087. array(0, 0, 0, 0, 0),
  2088. array(0, 0, 0, 0, 0),
  2089. array(0, 0, 0, 0, 0));
  2090. [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
  2091. % This will fail if sqrt isn't very accurate.
  2092. if addcircle(xxx, 2.0, 2, 2, 0.75) =
  2093. array(array(0, 0, 0.75, 0, 0),
  2094. array(0, 0.75, 0.75, 0.75, 0),
  2095. array(0.75, 0.75, 0.75, 0.75, 0.75),
  2096. array(0, 0.75, 0.75, 0.75, 0),
  2097. array(0, 0, 0.75, 0, 0))
  2098. then "Test 1 addcircle OK!"
  2099. else error(0, "Test 1 addcircle fails!");
  2100. "Test 1 addcircle OK!"
  2101. if addcircle(xxx, 10.0, 2, 2, 0.75) =
  2102. array(array(0.75, 0.75, 0.75, 0.75, 0.75),
  2103. array(0.75, 0.75, 0.75, 0.75, 0.75),
  2104. array(0.75, 0.75, 0.75, 0.75, 0.75),
  2105. array(0.75, 0.75, 0.75, 0.75, 0.75),
  2106. array(0.75, 0.75, 0.75, 0.75, 0.75))
  2107. then "Test 2 addcircle OK!"
  2108. else error(0, "Test 2 addcircle fails!");
  2109. "Test 2 addcircle OK!"
  2110. %------------------------- Exercise #10 -------------------------
  2111. expr procedure areaaverage(a, n);
  2112. /* AREAAVERAGE(A, N) -- Compute the average of the NxN
  2113. neighborhood of each cell in the matrix A and return a
  2114. new matrix with these values. */
  2115. begin scalar uax, uay, sm, cnt, b, n2;
  2116. n2 := n / 2;
  2117. b := mkarray(uax := upbv a, uay := upbv a[1]);
  2118. for x := 0:uax do
  2119. for y := 0:uay do
  2120. << sm := 0.0;
  2121. cnt := 0;
  2122. for xp := max(0, x - n2):min(uax, x + n2) do
  2123. for yp := max(0, y - n2):min(uay, y + n2) do
  2124. << sm := sm + a[xp,yp];
  2125. cnt := cnt + 1 >>;
  2126. b[x,y] := sm / cnt >>;
  2127. return b
  2128. end;
  2129. areaaverage
  2130. global '(ninth);
  2131. nil
  2132. xxx[2,2] := 1.0;
  2133. 1.0
  2134. ninth := 1.0 / 9.0;
  2135. 0.11111111111111
  2136. if areaaverage(xxx, 3) =
  2137. array(array(0.0, 0.0, 0.0, 0.0, 0.0),
  2138. array(0.0, ninth, ninth, ninth, 0.0),
  2139. array(0.0, ninth, ninth, ninth, 0.0),
  2140. array(0.0, ninth, ninth, ninth, 0.0),
  2141. array(0.0, 0.0, 0.0, 0.0, 0.0))
  2142. then "Test 1 areaaverage OK!"
  2143. else error(0, "Test 1 areaaverage Fails!");
  2144. "Test 1 areaaverage OK!"
  2145. %------------------------- Exercise #11 -------------------------
  2146. expr procedure laplace a;
  2147. /* LAPLACE(A) -- Compute the Laplacian on A but assuming
  2148. 0.0 at the borders. Returns a new array the same size
  2149. as A. */
  2150. begin scalar uax, uay, b, sm;
  2151. b := mkarray(uax := upbv a, uay := upbv a[0]);
  2152. for x := 0:uax do
  2153. for y := 0:uay do
  2154. << sm := 0.0;
  2155. for xp := max(0, x - 1):min(uax, x + 1)
  2156. when xp neq x do
  2157. for yp := max(0, y - 1):min(uay, y + 1)
  2158. when yp neq y
  2159. do sm := sm + a[xp,yp];
  2160. b[x,y] := max(0.0, min(5.0 * a[x,y] - sm, 1.0)) >>;
  2161. return b
  2162. end;
  2163. laplace
  2164. xxx := array(array(0,0,0,0,0),
  2165. array(0,1,1,1,0),
  2166. array(0,1,1,1,0),
  2167. array(0,1,1,1,0),
  2168. array(0,0,0,0,0));
  2169. [[0 0 0 0 0] [0 1 1 1 0] [0 1 1 1 0] [0 1 1 1 0] [0 0 0 0 0]]
  2170. if laplace xxx = array(array(0.0, 0.0, 0.0, 0.0, 0.0),
  2171. array(0.0, 1.0, 1.0, 1.0, 0.0),
  2172. array(0.0, 1.0, 1.0, 1.0, 0.0),
  2173. array(0.0, 1.0, 1.0, 1.0, 0.0),
  2174. array(0.0, 0.0, 0.0, 0.0, 0.0))
  2175. then "Test 1 laplace OK!"
  2176. else error(0, "Test 1 laplace fails!");
  2177. "Test 1 laplace OK!"
  2178. %------------------------- Exercise #12 -------------------------
  2179. expr procedure threshold(a, vl, vh);
  2180. /* THRESHOLD(A, VL, VH) -- Returns a new matrix of the same
  2181. size as A with each cell set to 1.0 that is
  2182. VL <= A(i,j) <= VH. Others are set to 0.0. */
  2183. for x := 0:uax
  2184. with uax, uay, b
  2185. initially b := mkarray(uax := upbv a,
  2186. uay := upbv a[0])
  2187. returns b
  2188. do for y := 0:uay
  2189. do b[x,y] :=
  2190. if a[x,y] >= vl and a[x,y] <= vh then 1.0
  2191. else 0.0;
  2192. threshold
  2193. xxx := mkarray(4,4);
  2194. [[nil nil nil nil nil] [nil nil nil nil nil] [nil nil nil nil nil] [nil nil nil
  2195. nil nil] [nil nil nil nil nil]]
  2196. for i:=0:4 do for j:=0:4 do xxx[i,j] := i * j;
  2197. nil
  2198. if threshold(xxx, 8, 10) = array(
  2199. array(0.0, 0.0, 0.0, 0.0, 0.0),
  2200. array(0.0, 0.0, 0.0, 0.0, 0.0),
  2201. array(0.0, 0.0, 0.0, 0.0, 1.0),
  2202. array(0.0, 0.0, 0.0, 1.0, 0.0),
  2203. array(0.0, 0.0, 1.0, 0.0, 0.0))
  2204. then "Test 1 threshold OK!"
  2205. else error(0, "Test 1 threshold Fails!");
  2206. "Test 1 threshold OK!"
  2207. expr procedure dump(a, f);
  2208. /* DUMP(A,F) -- Dump an array A into a PicTex format
  2209. file for document processing. */
  2210. begin scalar fh;
  2211. fh := wrs open(f, 'output);
  2212. for x:=0:upbv a do
  2213. for y:=0:upbv a[0] do
  2214. printf("\setshadegrid span <%wpt>%n\vshade %d %d %d %d %d %d /%n",
  2215. max(0.5, 5.5 - a[x,y]*5.0),
  2216. x, y, y+1, x+1, y, y+1);
  2217. close wrs fh;
  2218. end;
  2219. dump
  2220. % ##### Macro Exercises #####
  2221. %------------------------- Exercise -----------------------
  2222. macro procedure appendl x;
  2223. /* APPENDL( ...) - append all the lists together. */
  2224. expand(cdr x, 'append);
  2225. appendl
  2226. if appendl('(a b), '(c d), '(e f)) = '(a b c d e f)
  2227. then "Test 1 appendl OK!"
  2228. else error(0, "Test 1 appendl fails!");
  2229. "Test 1 appendl OK!"
  2230. if appendl '(a b c) = '(a b c)
  2231. then "Test 2 appendl OK!"
  2232. else error(0, "Test 2 appendl fails!");
  2233. "Test 2 appendl OK!"
  2234. if appendl nil = nil
  2235. then "Test 3 appendl OK!"
  2236. else error(0, "Test 3 appendl fails!");
  2237. "Test 3 appendl OK!"
  2238. %------------------------- Exercise ------------------------
  2239. macro procedure nconcl x;
  2240. /* NCONCL(...) - destructive concatenation of all the
  2241. lists. */
  2242. expand(cdr x, 'nconc);
  2243. nconcl
  2244. global '(b1 b2 b3);
  2245. nil
  2246. b1 := '(a b);
  2247. (a b)
  2248. b2 := '(c d);
  2249. (c d)
  2250. b3 := '(e f);
  2251. (e f)
  2252. if nconcl(b1, b2, b3) = '(a b c d e f)
  2253. then "Test 1 nconcl OK!"
  2254. else error(0, "Test 1 nconcl fails!");
  2255. "Test 1 nconcl OK!"
  2256. if b1 = '(a b c d e f)
  2257. then "Test 2 nconcl OK!"
  2258. else error(0, "Test 2 nconcl fails!");
  2259. "Test 2 nconcl OK!"
  2260. if b2 = '(c d e f)
  2261. then "Test 3 nconcl OK!"
  2262. else error(0, "Test 3 nconcl fails!");
  2263. "Test 3 nconcl OK!"
  2264. if b3 = '(e f)
  2265. then "Test 4 nconcl OK!"
  2266. else error(0, "Test 4 nconcl fails!");
  2267. "Test 4 nconcl OK!"
  2268. %------------------------- Exercise ------------------------
  2269. smacro procedure d(x1, y1, x2, y2);
  2270. /* D(X1, Y1, X2, Y2) - Euclidean distance between points
  2271. (X1,Y1) -> (X2,Y2) */
  2272. sqrt((x1 - x2)^2 + (y1 - y2)^2);
  2273. d
  2274. % This fails with poor sqrt.
  2275. if d(0, 0, 3, 4) = 5.0
  2276. then "Test 1 d OK!"
  2277. else error(0, "Test 1 d Fails!");
  2278. "Test 1 d OK!"
  2279. if d(0, 0, 1, 1) = sqrt 2
  2280. then "Test 2 d OK!"
  2281. else error(0, "Test 2 d Fails!");
  2282. "Test 2 d OK!"
  2283. %------------------------- Exercise -------------------------
  2284. macro procedure pop x;
  2285. /* POP(X) - Assuming X is an identifier, pop the stack
  2286. and return the popped value. */
  2287. (`(prog (!$V!$)
  2288. (setq !$V!$ (car #v))
  2289. (setq #v (cdr #v))
  2290. (return !$V!$))) where v := cadr x;
  2291. pop
  2292. xxx := '(A B);
  2293. (a b)
  2294. if pop xxx eq 'A
  2295. then "Test 1 POP ok!"
  2296. else error(0, "Test 1 POP fails!");
  2297. "Test 1 POP ok!"
  2298. if xxx = '(B)
  2299. then "Test 1 POP ok!"
  2300. else error(0, "Test 1 POP fails!");
  2301. "Test 1 POP ok!"
  2302. if pop xxx eq 'B
  2303. then "Test 2 POP ok!"
  2304. else error(0, "Test 2 POP fails!");
  2305. "Test 2 POP ok!"
  2306. if xxx eq NIL
  2307. then "Test 2 POP ok!"
  2308. else error(0, "Test 2 POP fails!");
  2309. "Test 2 POP ok!"
  2310. %------------------------- Exercise -------------------------
  2311. macro procedure push x;
  2312. /* PUSH(ST, V) - push V onto ST (an identifier) and
  2313. return V. */
  2314. `(progn (setq #st (cons #v #st))
  2315. #v)
  2316. where st := cadr x,
  2317. v := caddr x;
  2318. push
  2319. if push(xxx, 'A) = 'A
  2320. then "Test 1 push OK!"
  2321. else error(0, "Test 1 push fails");
  2322. "Test 1 push OK!"
  2323. if xxx = '(A)
  2324. then "Test 1 push OK!"
  2325. else error(0, "Test 1 push fails");
  2326. "Test 1 push OK!"
  2327. if push(xxx, 'B) = 'B
  2328. then "Test 2 push OK!"
  2329. else error(0, "Test 2 push fails");
  2330. "Test 2 push OK!"
  2331. if xxx = '(B A)
  2332. then "Test 2 push OK!"
  2333. else error(0, "Test 2 push fails");
  2334. "Test 2 push OK!"
  2335. %------------------------- Exercise -------------------------
  2336. macro procedure format x;
  2337. /* FORMAT("str", ...) - A formatted print utility. It
  2338. looks for %x things in str, printing everything else.
  2339. A property of printf!-format will cause a call on
  2340. the named function with the corresponding argument.
  2341. This should return a print form to use. A property
  2342. printf!-expand calls a function without an argument.
  2343. Common controls are:
  2344. %n new line
  2345. %p prin2 call.
  2346. %w prin1 call.
  2347. */
  2348. begin scalar str, localstr, m;
  2349. str := explode2 cadr x;
  2350. x := cddr x;
  2351. loop: if null str then
  2352. << if localstr then
  2353. m := {'prin2, makestring reversip localstr} . m;
  2354. return 'progn . reverse m >>;
  2355. if eqcar(str, '!%) then
  2356. if cdr str then
  2357. if fn := get(cadr str, 'printf!-format) then
  2358. << if localstr then
  2359. << m := {'prin2, makestring reversip localstr} . m;
  2360. localstr := nil >>;
  2361. m := apply(fn, {car x}) . m;
  2362. x := cdr x;
  2363. str := cddr str;
  2364. go to loop >>
  2365. else if fn := get(cadr str, 'printf!-expand) then
  2366. << if localstr then
  2367. << m := {'prin2, makestring reverse localstr} . m;
  2368. localstr := nil >>;
  2369. m := apply(fn, nil) . m;
  2370. str := cddr str;
  2371. go to loop >>;
  2372. localstr := car str . localstr;
  2373. str := cdr str;
  2374. go to loop
  2375. end;
  2376. format
  2377. expr procedure makestring l;
  2378. /* MAKESTRING(L) - convert the list of character L into
  2379. a string. */
  2380. compress('!" . append(l, '(!")));
  2381. makestring
  2382. expr procedure printf!-terpri;
  2383. /* PRINTF!-TERPRI() - Generates a TERPRI call for %n */
  2384. '(terpri);
  2385. printf!-terpri
  2386. put('!n, 'printf!-expand, 'printf!-terpri);
  2387. printf!-terpri
  2388. put('!N, 'printf!-expand, 'printf!-terpri);
  2389. printf!-terpri
  2390. expr procedure printf!-prin1 x;
  2391. /* PRINTF!-PRIN1(X) - Generates a PRIN1 call for %w */
  2392. {'prin1, x};
  2393. printf!-prin1
  2394. put('!w, 'printf!-format, 'printf!-prin1);
  2395. printf!-prin1
  2396. put('!W, 'printf!-format, 'printf!-prin1);
  2397. printf!-prin1
  2398. expr procedure printf!-prin2 x;
  2399. /* PRINTF!-PRIN2(X) - Generates a PRIN2 call for %p */
  2400. {'prin2, x};
  2401. printf!-prin2
  2402. put('!p, 'printf!-format, 'printf!-prin2);
  2403. printf!-prin2
  2404. put('!P, 'printf!-format, 'printf!-prin2);
  2405. printf!-prin2
  2406. %------------------------- Exercise -------------------------
  2407. macro procedure rmsg x;
  2408. /* RMSG("str", ...) - A formatted string utility. It
  2409. looks for %x things in str, copying everything else.
  2410. A property of rmsg!-format will cause a call on
  2411. the named function with the corresponding argument.
  2412. This should return a explode form to use. A property
  2413. rmsg!-expand calls a function without an argument.
  2414. Common controls are:
  2415. %n new line
  2416. %p explode2 call.
  2417. %w explode call.
  2418. */
  2419. begin scalar str, localstr, m;
  2420. str := explode2 cadr x;
  2421. x := cddr x;
  2422. loop: if null str then
  2423. << if localstr then
  2424. m := mkquote reversip localstr . m;
  2425. return `(makestring (nconcl #@(reversip m))) >>;
  2426. if eqcar(str, '!%) then
  2427. if cdr str then
  2428. if fn := get(cadr str, 'rmsg!-format) then
  2429. << if localstr then
  2430. << m := mkquote reversip localstr . m;
  2431. localstr := nil >>;
  2432. m := apply(fn, {car x}) . m;
  2433. x := cdr x;
  2434. str := cddr str;
  2435. go to loop >>
  2436. else if fn := get(cadr str, 'rmsg!-expand) then
  2437. << if localstr then
  2438. << m := mkquote reversip localstr . m;
  2439. localstr := nil >>;
  2440. m := apply(fn, nil) . m;
  2441. str := cddr str;
  2442. go to loop >>;
  2443. localstr := car str . localstr;
  2444. str := cdr str;
  2445. go to loop
  2446. end;
  2447. rmsg
  2448. expr procedure makestring l;
  2449. /* MAKESTRING(L) - convert the list of character L into
  2450. a string. */
  2451. compress('!" . append(l, '(!")));
  2452. +++ makestring redefined
  2453. makestring
  2454. expr procedure rmsg!-terpri;
  2455. /* RMSG!-TERPRI() - Generates an EOL. */
  2456. mkquote {!$eol!$};
  2457. rmsg!-terpri
  2458. put('!n, 'rmsg!-expand, 'rmsg!-terpri);
  2459. rmsg!-terpri
  2460. put('!N, 'rmsg!-expand, 'rmsg!-terpri);
  2461. rmsg!-terpri
  2462. expr procedure rmsg!-prin1 x;
  2463. /* RMSG!-PRIN1(X) - Generates an EXPLODE call */
  2464. `(fixstr (explode #x));
  2465. rmsg!-prin1
  2466. put('!w, 'rmsg!-format, 'rmsg!-prin1);
  2467. rmsg!-prin1
  2468. put('!W, 'rmsg!-format, 'rmsg!-prin1);
  2469. rmsg!-prin1
  2470. expr procedure rmsg!-prin2 x;
  2471. /* RMSG!-PRIN2(X) - Generates an EXPLODE2 call for x. */
  2472. `(explode2 #x);
  2473. rmsg!-prin2
  2474. put('!p, 'rmsg!-format, 'rmsg!-prin2);
  2475. rmsg!-prin2
  2476. put('!P, 'rmsg!-format, 'rmsg!-prin2);
  2477. rmsg!-prin2
  2478. expr procedure fixstr x;
  2479. /* FIXSTR(X) - Double up "'s in x. */
  2480. if null x then nil
  2481. else if eqcar(x, '!") then '!" . '!" . fixstr cdr x
  2482. else car x . fixstr cdr x;
  2483. fixstr
  2484. if rmsg "abc" = "abc"
  2485. then "Test 1 rmsg OK!"
  2486. else error(0, "Test 1 rmsg fails!");
  2487. "Test 1 rmsg OK!"
  2488. if rmsg("Test %w test", 12) = "Test 12 test"
  2489. then "Test 2 rmsg OK!"
  2490. else error(0, "Test 2 rmsg fails!");
  2491. "Test 2 rmsg OK!"
  2492. if rmsg("Test %w string", "foo") = "Test ""foo"" string"
  2493. then "Test 3 rmsg OK!"
  2494. else error(0, "Test 3 rmsg fails!");
  2495. "Test 3 rmsg OK!"
  2496. if rmsg("Test %w now %p", "foo", "foo") = "Test ""foo"" now foo"
  2497. then "Test 4 rmsg OK!"
  2498. else error(0, "Test 4 rmsg fails!");
  2499. "Test 4 rmsg OK!"
  2500. %------------------------- Exercise -------------------------
  2501. define CFLAG = T;
  2502. nil
  2503. macro procedure ifcflag x;
  2504. /* IFCLFAG(X) - generate the code for X if CFLAG is non-NIL,
  2505. otherwise generate NIL (this can't be used everywhere). */
  2506. if CFLAG then cadr x else nil;
  2507. ifcflag
  2508. ifCFLAG expr procedure pslfoo x; car x;
  2509. pslfoo
  2510. if getd 'pslfoo
  2511. then "Test 1 ifCFLAG OK!"
  2512. else error(0, "Test 1 ifCFLAG fails!");
  2513. "Test 1 ifCFLAG OK!"
  2514. % ##### Interactive Exercises #####
  2515. %------------------------- Exercise #2 -------------------------
  2516. /* Lists functions that have been embedded with count code. */
  2517. global '(EMBEDDED!*);
  2518. nil
  2519. EMBEDDED!* := NIL;
  2520. nil
  2521. expr procedure embed f;
  2522. /* EMBED(F) - wrap function F with counter code. Error if F is
  2523. not interpreted. Put the information under property COUNT and
  2524. add to the global list EMBEDDED!*. */
  2525. begin scalar def, args, nfn;
  2526. if not(def := getd f) then error(0, {f, "is undefined"});
  2527. if codep cdr def then error(0, {f, "is not interpreted"});
  2528. put(f, 'COUNT, 0);
  2529. if f memq EMBEDDED!* then return NIL;
  2530. EMBEDDED!* := f . EMBEDDED!*;
  2531. putd(nfn := intern gensym(), car def, cdr def);
  2532. putd(f, car def,
  2533. {'lambda, caddr def,
  2534. {'progn,
  2535. {'put, mkquote f, mkquote 'COUNT,
  2536. {'add1, {'get, mkquote f, mkquote 'COUNT}}},
  2537. nfn . caddr def}});
  2538. return f
  2539. end;
  2540. *** local variable args in procedure embed not used
  2541. embed
  2542. expr procedure stats;
  2543. /* STATS() - list all the embedded functions and their
  2544. counts. */
  2545. for each f in EMBEDDED!*
  2546. do << prin1 f; prin2 " "; print get(f, 'COUNT) >>;
  2547. stats
  2548. expr procedure pcnt x;
  2549. /* PCNT(X) - returns the number of dotted-pairs in X (vectors
  2550. can hide dotted-pairs). */
  2551. if atom x then 0
  2552. else 1 + pcnt car x + pcnt cdr x;
  2553. pcnt
  2554. if embed 'pcnt eq 'pcnt
  2555. then "Test 1 embed OK!"
  2556. else error(0, "Test 1 embed Fails!");
  2557. +++ pcnt redefined
  2558. "Test 1 embed OK!"
  2559. if get('pcnt, 'count) = 0
  2560. then "Test 2 embed OK!"
  2561. else error(0, "Test 2 embed Fails!");
  2562. "Test 2 embed OK!"
  2563. if pcnt '(a . (b . c)) = 2
  2564. then "Test 3 embed OK!"
  2565. else error(0, "Test 3 embed Fails!");
  2566. "Test 3 embed OK!"
  2567. if get('pcnt, 'COUNT) = 5
  2568. then "Test 4 embed OK!"
  2569. else error(0, "Test 4 embed Fails!");
  2570. "Test 4 embed OK!"
  2571. if EMBEDDED!* = '(PCNT)
  2572. then "Test 5 embed OK!"
  2573. else error(0, "Test 5 embed Fails!");
  2574. "Test 5 embed OK!"
  2575. % Just a visual check.
  2576. stats();
  2577. pcnt 5
  2578. nil
  2579. % ##### Test the inspector module #####
  2580. %
  2581. % We set LINELENGTH to various values to check how good we do on output.
  2582. % Don't let the default screw up the test:
  2583. LINELENGTH 80;
  2584. t
  2585. % Describe some of the basic data types.
  2586. % Dotted-pairs.
  2587. describe '(a . b);
  2588. A dotted-pair or list
  2589. nil
  2590. % Vectors;
  2591. global '(xvar);
  2592. nil
  2593. xvar := mkvect 3;
  2594. [nil nil nil nil]
  2595. describe xvar;
  2596. A vector with 4 elements
  2597. nil
  2598. % Records.
  2599. record insprec /* A record for testing. */
  2600. with
  2601. field1 := 'a;
  2602. insprec
  2603. xvar := insprec();
  2604. [insprec a]
  2605. describe xvar;
  2606. A insprec record with
  2607. 1: a
  2608. nil
  2609. describe 'insprec;
  2610. insprec is a record constructor with the following fields
  2611. ** not implemented. **
  2612. nil
  2613. % A code pointer (usually).
  2614. describe cdr getd 'car;
  2615. car is an EXPR with an unknown number of arguments
  2616. nil
  2617. % Numbers.
  2618. describe 1;
  2619. A fixed number
  2620. nil
  2621. describe 3.14159;
  2622. A floating-point number
  2623. nil
  2624. % Strings
  2625. describe "This is a string";
  2626. A string
  2627. nil
  2628. % identifiers of various sourts.
  2629. describe 'car;
  2630. car is an EXPR with one argument
  2631. nil
  2632. describe 'a!-plain!-jane!-identifier;
  2633. Don't know anything about a!-plain!-jane!-identifier
  2634. nil
  2635. describe nil;
  2636. Identifier 'nil' is fluid
  2637. nil
  2638. % This message is sort of funny in odd ways.
  2639. % Now let's get serious. Here's a global with no active comment. The
  2640. % remprop is something you shouldn't know about but allows us to run
  2641. % the test file multiple times and get the same results.
  2642. remprop('TheCow, 'NEWNAM);
  2643. nil
  2644. DEFINE TheCow = "How now brown cow";
  2645. nil
  2646. describe 'TheCow;
  2647. thecow is a constant defined as "How now brown cow"
  2648. nil
  2649. off saveactives;
  2650. nil
  2651. /* I never saw a purple cow, I never hope to see one now. */
  2652. global '(PurpleCow);
  2653. nil
  2654. describe 'PurpleCow;
  2655. Identifier 'purplecow' is global
  2656. nil
  2657. on saveactives;
  2658. nil
  2659. /* But I'd rather see one than be one! */
  2660. global '(Pcow);
  2661. nil
  2662. describe 'Pcow;
  2663. Identifier 'pcow' is global defined line 2236 in file ../xmpl/rlisp88.tst
  2664. but i'd rather see one than be one!
  2665. nil
  2666. % Now we march on to procedures.
  2667. % Here's one with no comment and we don't save it.
  2668. off saveactives;
  2669. nil
  2670. remd 'comtest1;
  2671. nil
  2672. expr procedure comtest1 x;
  2673. print x;
  2674. comtest1
  2675. describe 'comtest1;
  2676. comtest1 is an EXPR with one argument
  2677. nil
  2678. % Here's one with no comment and we do save it.
  2679. on saveactives;
  2680. nil
  2681. remd 'comtest2;
  2682. nil
  2683. expr procedure comtest2(x, y);
  2684. print x;
  2685. *** local variable y in procedure comtest2 not used
  2686. comtest2
  2687. describe 'comtest2;
  2688. comtest2 is an EXPR with 2 arguments
  2689. nil
  2690. % Here's one with a comment but we don't save it.
  2691. off saveactives;
  2692. nil
  2693. remd 'comtest3;
  2694. nil
  2695. expr procedure comtest3(x, y, z);
  2696. /* You should never see this comment. */
  2697. print x;
  2698. *** local variable y in procedure comtest3 not used
  2699. *** local variable z in procedure comtest3 not used
  2700. comtest3
  2701. describe 'comtest3;
  2702. comtest3 is an EXPR with 3 arguments
  2703. nil
  2704. % Here's one with a comment and we should see it.
  2705. on saveactives;
  2706. nil
  2707. remd 'comtest4;
  2708. nil
  2709. expr procedure comtest4(x, y, z, xx);
  2710. /* COMTEST4(X, Y, Z, XX) - A well commented routine. This routine
  2711. does almost nothing, but a good article thereof. */
  2712. print x;
  2713. *** local variable y in procedure comtest4 not used
  2714. *** local variable z in procedure comtest4 not used
  2715. *** local variable xx in procedure comtest4 not used
  2716. comtest4
  2717. describe 'comtest4;
  2718. comtest4 is an EXPR with 4 arguments
  2719. Function ends on line 2265 in file ../xmpl/rlisp88.tst
  2720. comtest4(x, y, z, xx) - a well commented routine. this routine
  2721. does almost nothing, but a good article thereof.
  2722. nil
  2723. % Now try MACROS.
  2724. remd 'comtest5;
  2725. nil
  2726. macro procedure comtest5 x;
  2727. /* COMTEST5(X) - A macro that doesn't really do much of anything. */
  2728. {'car, cadr x};
  2729. comtest5
  2730. describe 'comtest5;
  2731. comtest5 is a MACRO
  2732. Function ends on line 2272 in file ../xmpl/rlisp88.tst
  2733. comtest5(x) - a macro that doesn't really do much of anything.
  2734. nil
  2735. smacro procedure comtest6 x;
  2736. /* COMTEST6(X) - a SMACRO with an active comment. This smacro expands
  2737. to take CAR of its argument. */
  2738. car x;
  2739. comtest6
  2740. describe 'comtest6;
  2741. comtest6 is an SMACRO with one argument
  2742. Function ends on line 2277 in file ../xmpl/rlisp88.tst
  2743. comtest6(x) - a smacro with an active comment. this smacro expands
  2744. to take car of its argument.
  2745. nil
  2746. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2747. % Module testing.
  2748. /* This is a test module which occurs at the top level just to make
  2749. sure that the module type works. */
  2750. module testmodule;
  2751. nil
  2752. endmodule;
  2753. nil
  2754. describe 'testmodule;
  2755. Can't find source or fasl file for module testmodule
  2756. this is a test module which occurs at the top level just to make
  2757. sure that the module type works.
  2758. nil
  2759. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2760. % Format testing. Put a big comment out there and look at it with
  2761. % various line lengths.
  2762. /* ********************
  2763. This is a test comment. We'll try do different things with it in
  2764. different contexts. Does it work?
  2765. expr procedure fact n;
  2766. if n < 2 then 1 else n * fact(n - 1);
  2767. Well hoop de doo! Is there anything else funny?
  2768. +------------+----------+
  2769. | Column 1 | Col. 2 |
  2770. +------------+----------+
  2771. | Aardvarks | 345 |
  2772. +------------+----------+
  2773. | Zarfs | 3 |
  2774. +------------+----------+
  2775. /// */
  2776. global '(testvariable);
  2777. nil
  2778. describe 'testvariable;
  2779. Identifier 'testvariable' is global defined line 2292 in file
  2780. ../xmpl/rlisp88.tst
  2781. ********************
  2782. this is a test comment. we'll try do different things with it in
  2783. different contexts. does it work?
  2784. expr procedure fact n;
  2785. if n < 2 then 1 else n * fact(n - 1);
  2786. well hoop de doo! is there anything else funny?
  2787. +------------+----------+
  2788. | column 1 | col. 2 |
  2789. +------------+----------+
  2790. | aardvarks | 345 |
  2791. +------------+----------+
  2792. | zarfs | 3 |
  2793. +------------+----------+
  2794. ///
  2795. nil
  2796. LINELENGTH 60;
  2797. 80
  2798. describe 'testvariable;
  2799. Identifier 'testvariable' is global defined line 2292
  2800. in file ../xmpl/rlisp88.tst
  2801. ********************
  2802. this is a test comment. we'll try do different things with i
  2803. t in
  2804. different contexts. does it work?
  2805. expr procedure fact n;
  2806. if n < 2 then 1 else n * fact(n - 1);
  2807. well hoop de doo! is there anything else funny?
  2808. +------------+----------+
  2809. | column 1 | col. 2 |
  2810. +------------+----------+
  2811. | aardvarks | 345 |
  2812. +------------+----------+
  2813. | zarfs | 3 |
  2814. +------------+----------+
  2815. ///
  2816. nil
  2817. LINELENGTH 50;
  2818. 60
  2819. describe 'testvariable;
  2820. Identifier 'testvariable' is global defined line
  2821. 2292 in file ../xmpl/rlisp88.tst
  2822. ********************
  2823. this is a test comment. we'll try do different thi
  2824. ngs with it in
  2825. different contexts. does it work?
  2826. expr procedure fact n;
  2827. if n < 2 then 1 else n * fact(n - 1);
  2828. well hoop de doo! is there anything else funny?
  2829. +------------+----------+
  2830. | column 1 | col. 2 |
  2831. +------------+----------+
  2832. | aardvarks | 345 |
  2833. +------------+----------+
  2834. | zarfs | 3 |
  2835. +------------+----------+
  2836. ///
  2837. nil
  2838. LINELENGTH 40;
  2839. 50
  2840. describe 'testvariable;
  2841. Identifier 'testvariable' is global
  2842. defined line 2292 in file
  2843. ../xmpl/rlisp88.tst
  2844. ********************
  2845. this is a test comment. we'll try do dif
  2846. ferent things with it in
  2847. different contexts. does it work?
  2848. expr procedure fact n;
  2849. if n < 2 then 1 else n * fact(n - 1)
  2850. ;
  2851. well hoop de doo! is there anything else
  2852. funny?
  2853. +------------+----------+
  2854. | column 1 | col. 2 |
  2855. +------------+----------+
  2856. | aardvarks | 345 |
  2857. +------------+----------+
  2858. | zarfs | 3 |
  2859. +------------+----------+
  2860. ///
  2861. nil
  2862. LINELENGTH 30;
  2863. 40
  2864. describe 'testvariable;
  2865. Identifier 'testvariable' is
  2866. global defined line 2292
  2867. in file ../xmpl/rlisp88.tst
  2868. ********************
  2869. this is a test comment. we'll
  2870. try do different things with i
  2871. t in
  2872. different contexts. does it wo
  2873. rk?
  2874. expr procedure fact n;
  2875. if n < 2 then 1 else n * f
  2876. act(n - 1);
  2877. well hoop de doo! is there any
  2878. thing else funny?
  2879. +------------+----------+
  2880. | column 1 | col. 2 |
  2881. +------------+----------+
  2882. | aardvarks | 345 |
  2883. +------------+----------+
  2884. | zarfs | 3 |
  2885. +------------+----------+
  2886. ///
  2887. nil
  2888. LINELENGTH 20;
  2889. 30
  2890. describe 'testvariable;
  2891. Identifier '
  2892. testvariable' is
  2893. global defined line
  2894. 2292 in file
  2895. ../xmpl/rlisp88.tst
  2896. ********************
  2897. this is a test comme
  2898. nt. we'll try do dif
  2899. ferent things with i
  2900. t in
  2901. different contexts.
  2902. does it work?
  2903. expr procedure fac
  2904. t n;
  2905. if n < 2 then 1
  2906. else n * fact(n - 1)
  2907. ;
  2908. well hoop de doo! is
  2909. there anything else
  2910. funny?
  2911. +------------+-----
  2912. -----+
  2913. | column 1 | col
  2914. . 2 |
  2915. +------------+-----
  2916. -----+
  2917. | aardvarks |
  2918. 345 |
  2919. +------------+-----
  2920. -----+
  2921. | zarfs |
  2922. 3 |
  2923. +------------+-----
  2924. -----+
  2925. ///
  2926. nil
  2927. LINELENGTH 10;
  2928. 20
  2929. describe 'testvariable;
  2930. Identifier '
  2931. testvariable
  2932. ' is
  2933. global
  2934. defined line
  2935. 2292
  2936. in file
  2937. ../xmpl/rlisp88.tst
  2938. **********
  2939. **********
  2940. this is a
  2941. test comme
  2942. nt. we'll
  2943. try do dif
  2944. ferent thi
  2945. ngs with i
  2946. t in
  2947. different
  2948. contexts.
  2949. does it wo
  2950. rk?
  2951. expr pro
  2952. cedure fac
  2953. t n;
  2954. if n <
  2955. 2 then 1
  2956. else n * f
  2957. act(n - 1)
  2958. ;
  2959. well hoop
  2960. de doo! is
  2961. there any
  2962. thing else
  2963. funny?
  2964. +--------
  2965. ----+-----
  2966. -----+
  2967. | column
  2968. 1 | col
  2969. . 2 |
  2970. +--------
  2971. ----+-----
  2972. -----+
  2973. | aardvar
  2974. ks |
  2975. 345 |
  2976. +--------
  2977. ----+-----
  2978. -----+
  2979. | zarfs
  2980. |
  2981. 3 |
  2982. +--------
  2983. ----+-----
  2984. -----+
  2985. ///
  2986. nil
  2987. % ##### Records Package #####
  2988. global '(rec1 rec2);
  2989. nil
  2990. % Simple test.
  2991. record rtest1;
  2992. rtest1
  2993. rec1 := rtest1();
  2994. [rtest1]
  2995. if rec1 neq array 'rtest1 then
  2996. error(0, "Test 1 RECORD fails creation test!");
  2997. nil
  2998. if null rtest1p rec1 then
  2999. error(0, "Test 1 RECORD fails predicate test!");
  3000. nil
  3001. % A record with two fields.
  3002. record rtest2 with field1 := 0, field2 := 1;
  3003. rtest2
  3004. % Test default creation.
  3005. rec2 := rtest2();
  3006. [rtest2 0 1
  3007. ]
  3008. if rec2 neq array('rtest2, 0, 1) then
  3009. error(0, "Test 2 RECORD fails to create a record");
  3010. nil
  3011. if null rtest2p rec2 then
  3012. error(0, "Test 2 RECORD fails predicate test");
  3013. nil
  3014. if rtest2p rec1 then
  3015. error(0, "Test 2 RECORD fails to test record differences");
  3016. nil
  3017. % Build a record with a predicate. Remove any old occurrence.
  3018. remd 'rtest3!?;
  3019. nil
  3020. record rtest3 with field1 := 0, field2 := 1 has predicate = rtest3!?;
  3021. rtest3
  3022. if not getd 'rtest3!? then
  3023. error(0, "Test 3 RECORD fails - no predicate built");
  3024. nil
  3025. if rtest3!? rec2 then
  3026. error(0, "Test 3 RECORD fails - predicate returns T on non RTEST3 record");
  3027. nil
  3028. for each x in {'identifier, 12, 12.3, "a string", cdr getd 'car,
  3029. '(a list), array("an", "array")}
  3030. when rtest3!? x
  3031. do error(0, {"Test 3 RECORD fails - predicate returns T on", x});
  3032. nil
  3033. rec2 := rtest3();
  3034. [rtest3 0 1
  3035. ]
  3036. if not rtest3!? rec2 then
  3037. error(0, "Test 3 RECORD fails - predicate returns NIL on record");
  3038. nil
  3039. % Check that the no-predicate option works.
  3040. remd 'rtest4p;
  3041. nil
  3042. % Just to make sure.
  3043. record rtest4 with a := 34, b := 56 has no predicate;
  3044. rtest4
  3045. if getd 'rtest4p then
  3046. error(0, "Test 4 RECORD fails - NO PREDICATE option generates a predicate");
  3047. nil
  3048. % Verify that the CONSTRUCTOR option works.
  3049. remd 'rtest5;
  3050. nil
  3051. remd 'make-rtest5;
  3052. nil
  3053. record rtest5 with r5a := 0, r5b := 1 has constructor;
  3054. rtest5
  3055. if getd 'rtest5 then
  3056. error(0, "Test 5 RECORD fails - CONSTRUCTOR generates simple constructor");
  3057. nil
  3058. if not getd 'make-rtest5 then
  3059. error(0, "Test 5 RECORD fails - CONSTRUCTOR doesn't generate constructor");
  3060. nil
  3061. if not rtest5p make-rtest5() then
  3062. error(0, "Test 5 RECORD fails - CONSTRUCTOR doesn't generate record");
  3063. nil
  3064. % Verify that the named constructor works.
  3065. remd 'rtest6;
  3066. nil
  3067. remd 'please-make-rtest6;
  3068. nil
  3069. record rtest6 with r6a := 0 has constructor = please!-make!-arecord;
  3070. rtest6
  3071. if getd 'rtest6 then
  3072. error(0, "Test 6 RECORD fails - CONSTRUCTOR generates simple constructor");
  3073. nil
  3074. if getd 'make-rtest6 then
  3075. error(0, "Test 6 RECORD fails - CONSTRUCTOR generates make- constructor");
  3076. nil
  3077. if not getd 'please-make-arecord then
  3078. error(0, "Test 6 RECORD fails - CONSTRUCTOR doesn't generate constructor");
  3079. nil
  3080. if not rtest6p please-make-arecord() then
  3081. error(0, "Test 6 RECORD fails - CONSTRUCTOR doesn't generate record");
  3082. nil
  3083. end;
  3084. (TIME:
  3085. rlisp88
  3086. 1999 2009)
  3087. nil