| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540 |
- /* T I N Y S C H E M E 1 . 3 9
- * Dimitrios Souflis (dsouflis@acm.org)
- * Based on MiniScheme (original credits follow)
- * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
- * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
- * (MINISCM) This version has been modified by R.C. Secrist.
- * (MINISCM)
- * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
- * (MINISCM)
- * (MINISCM) This is a revised and modified version by Akira KIDA.
- * (MINISCM) current version is 0.85k4 (15 May 1994)
- *
- */
- #define _SCHEME_SOURCE
- #include "scheme-private.h"
- #ifndef WIN32
- # include <unistd.h>
- #endif
- #if USE_DL
- # include "dynload.h"
- #endif
- #if USE_MATH
- # include <math.h>
- #endif
- #include <limits.h>
- #include <float.h>
- #include <ctype.h>
- #if USE_STRCASECMP
- #include <strings.h>
- # ifndef __APPLE__
- # define stricmp strcasecmp
- # endif
- #endif
- /* Used for documentation purposes, to signal functions in 'interface' */
- #define INTERFACE
- #define TOK_EOF (-1)
- #define TOK_LPAREN 0
- #define TOK_RPAREN 1
- #define TOK_DOT 2
- #define TOK_ATOM 3
- #define TOK_QUOTE 4
- #define TOK_COMMENT 5
- #define TOK_DQUOTE 6
- #define TOK_BQUOTE 7
- #define TOK_COMMA 8
- #define TOK_ATMARK 9
- #define TOK_SHARP 10
- #define TOK_SHARP_CONST 11
- #define TOK_VEC 12
- # define BACKQUOTE '`'
- /*
- * Basic memory allocation units
- */
- #define banner "TinyScheme 1.39"
- #include <string.h>
- #include <stdlib.h>
- #ifndef __APPLE__
- # include <malloc.h>
- #else
- static int stricmp(const char *s1, const char *s2)
- {
- unsigned char c1, c2;
- do {
- c1 = tolower(*s1);
- c2 = tolower(*s2);
- if (c1 < c2)
- return -1;
- else if (c1 > c2)
- return 1;
- s1++, s2++;
- } while (c1 != 0);
- return 0;
- }
- #endif /* __APPLE__ */
- #if USE_STRLWR
- static const char *strlwr(char *s) {
- const char *p=s;
- while(*s) {
- *s=tolower(*s);
- s++;
- }
- return p;
- }
- #endif
- #ifndef prompt
- # define prompt "> "
- #endif
- #ifndef InitFile
- # define InitFile "init.scm"
- #endif
- #ifndef FIRST_CELLSEGS
- # define FIRST_CELLSEGS 3
- #endif
- enum scheme_types {
- T_STRING=1,
- T_NUMBER=2,
- T_SYMBOL=3,
- T_PROC=4,
- T_PAIR=5,
- T_CLOSURE=6,
- T_CONTINUATION=7,
- T_FOREIGN=8,
- T_CHARACTER=9,
- T_PORT=10,
- T_VECTOR=11,
- T_MACRO=12,
- T_PROMISE=13,
- T_ENVIRONMENT=14,
- T_LAST_SYSTEM_TYPE=14
- };
- /* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
- #define ADJ 32
- #define TYPE_BITS 5
- #define T_MASKTYPE 31 /* 0000000000011111 */
- #define T_SYNTAX 4096 /* 0001000000000000 */
- #define T_IMMUTABLE 8192 /* 0010000000000000 */
- #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
- #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
- #define MARK 32768 /* 1000000000000000 */
- #define UNMARK 32767 /* 0111111111111111 */
- static num num_add(num a, num b);
- static num num_mul(num a, num b);
- static num num_div(num a, num b);
- static num num_intdiv(num a, num b);
- static num num_sub(num a, num b);
- static num num_rem(num a, num b);
- static num num_mod(num a, num b);
- static int num_eq(num a, num b);
- static int num_gt(num a, num b);
- static int num_ge(num a, num b);
- static int num_lt(num a, num b);
- static int num_le(num a, num b);
- #if USE_MATH
- static double round_per_R5RS(double x);
- #endif
- static int is_zero_double(double x);
- static num num_zero;
- static num num_one;
- /* macros for cell operations */
- #define typeflag(p) ((p)->_flag)
- #define type(p) (typeflag(p)&T_MASKTYPE)
- INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
- #define strvalue(p) ((p)->_object._string._svalue)
- #define strlength(p) ((p)->_object._string._length)
- INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
- INTERFACE static void fill_vector(pointer vec, pointer obj);
- INTERFACE static pointer vector_elem(pointer vec, int ielem);
- INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
- INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); }
- INTERFACE INLINE int is_integer(pointer p) {
- return ((p)->_object._number.is_fixnum);
- }
- INTERFACE INLINE int is_real(pointer p) {
- return (!(p)->_object._number.is_fixnum);
- }
- INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
- INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
- INLINE num nvalue(pointer p) { return ((p)->_object._number); }
- INTERFACE long ivalue(pointer p) { return (is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
- INTERFACE double rvalue(pointer p) { return (!is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
- #define ivalue_unchecked(p) ((p)->_object._number.value.ivalue)
- #define rvalue_unchecked(p) ((p)->_object._number.value.rvalue)
- #define set_integer(p) (p)->_object._number.is_fixnum=1;
- #define set_real(p) (p)->_object._number.is_fixnum=0;
- INTERFACE long charvalue(pointer p) { return ivalue_unchecked(p); }
- INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); }
- #define is_inport(p) (type(p)==T_PORT && p->_object._port->kind&port_input)
- #define is_outport(p) (type(p)==T_PORT && p->_object._port->kind&port_output)
- INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); }
- #define car(p) ((p)->_object._cons._car)
- #define cdr(p) ((p)->_object._cons._cdr)
- INTERFACE pointer pair_car(pointer p) { return car(p); }
- INTERFACE pointer pair_cdr(pointer p) { return cdr(p); }
- INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
- INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
- INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); }
- INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); }
- #if USE_PLIST
- SCHEME_EXPORT INLINE int hasprop(pointer p) { return (typeflag(p)&T_SYMBOL); }
- #define symprop(p) cdr(p)
- #endif
- INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); }
- INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); }
- INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); }
- INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
- #define procnum(p) ivalue(p)
- static const char *procname(pointer x);
- INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); }
- INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); }
- INTERFACE INLINE pointer closure_code(pointer p) { return car(p); }
- INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); }
- INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); }
- #define cont_dump(p) cdr(p)
- /* To do: promise should be forced ONCE only */
- INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); }
- INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
- #define setenvironment(p) typeflag(p) = T_ENVIRONMENT
- #define is_atom(p) (typeflag(p)&T_ATOM)
- #define setatom(p) typeflag(p) |= T_ATOM
- #define clratom(p) typeflag(p) &= CLRATOM
- #define is_mark(p) (typeflag(p)&MARK)
- #define setmark(p) typeflag(p) |= MARK
- #define clrmark(p) typeflag(p) &= UNMARK
- INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
- /*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/
- INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
- #define caar(p) car(car(p))
- #define cadr(p) car(cdr(p))
- #define cdar(p) cdr(car(p))
- #define cddr(p) cdr(cdr(p))
- #define cadar(p) car(cdr(car(p)))
- #define caddr(p) car(cdr(cdr(p)))
- #define cadaar(p) car(cdr(car(car(p))))
- #define cadddr(p) car(cdr(cdr(cdr(p))))
- #define cddddr(p) cdr(cdr(cdr(cdr(p))))
- #if USE_CHAR_CLASSIFIERS
- static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
- static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
- static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
- static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
- static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
- #endif
- #if USE_ASCII_NAMES
- static const char *charnames[32]={
- "nul",
- "soh",
- "stx",
- "etx",
- "eot",
- "enq",
- "ack",
- "bel",
- "bs",
- "ht",
- "lf",
- "vt",
- "ff",
- "cr",
- "so",
- "si",
- "dle",
- "dc1",
- "dc2",
- "dc3",
- "dc4",
- "nak",
- "syn",
- "etb",
- "can",
- "em",
- "sub",
- "esc",
- "fs",
- "gs",
- "rs",
- "us"
- };
- static int is_ascii_name(const char *name, int *pc) {
- int i;
- for(i=0; i<32; i++) {
- if(stricmp(name,charnames[i])==0) {
- *pc=i;
- return 1;
- }
- }
- if(stricmp(name,"del")==0) {
- *pc=127;
- return 1;
- }
- return 0;
- }
- #endif
- static int file_push(scheme *sc, const char *fname);
- static void file_pop(scheme *sc);
- static int file_interactive(scheme *sc);
- static INLINE int is_one_of(char *s, int c);
- static int alloc_cellseg(scheme *sc, int n);
- static long binary_decode(const char *s);
- static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
- static pointer _get_cell(scheme *sc, pointer a, pointer b);
- static pointer reserve_cells(scheme *sc, int n);
- static pointer get_consecutive_cells(scheme *sc, int n);
- static pointer find_consecutive_cells(scheme *sc, int n);
- static void finalize_cell(scheme *sc, pointer a);
- static int count_consecutive_cells(pointer x, int needed);
- static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
- static pointer mk_number(scheme *sc, num n);
- static pointer mk_empty_string(scheme *sc, int len, char fill);
- static char *store_string(scheme *sc, int len, const char *str, char fill);
- static pointer mk_vector(scheme *sc, int len);
- static pointer mk_atom(scheme *sc, char *q);
- static pointer mk_sharp_const(scheme *sc, char *name);
- static pointer mk_port(scheme *sc, port *p);
- static pointer port_from_filename(scheme *sc, const char *fn, int prop);
- static pointer port_from_file(scheme *sc, FILE *, int prop);
- static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
- static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
- static port *port_rep_from_file(scheme *sc, FILE *, int prop);
- static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
- static void port_close(scheme *sc, pointer p, int flag);
- static void mark(pointer a);
- static void gc(scheme *sc, pointer a, pointer b);
- static int basic_inchar(port *pt);
- static int inchar(scheme *sc);
- static void backchar(scheme *sc, int c);
- static char *readstr_upto(scheme *sc, char *delim);
- static pointer readstrexp(scheme *sc);
- static INLINE void skipspace(scheme *sc);
- static int token(scheme *sc);
- static void printslashstring(scheme *sc, char *s, int len);
- static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen);
- static void printatom(scheme *sc, pointer l, int f);
- static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
- static pointer mk_closure(scheme *sc, pointer c, pointer e);
- static pointer mk_continuation(scheme *sc, pointer d);
- static pointer reverse(scheme *sc, pointer a);
- static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
- static pointer append(scheme *sc, pointer a, pointer b);
- static int list_length(scheme *sc, pointer a);
- static int eqv(pointer a, pointer b);
- static void dump_stack_mark(scheme *);
- static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
- static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
- static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
- static void assign_syntax(scheme *sc, char *name);
- static int syntaxnum(pointer p);
- static void assign_proc(scheme *sc, enum scheme_opcodes, char *name);
- #define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
- #define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
- static num num_add(num a, num b) {
- num ret;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- if(ret.is_fixnum) {
- ret.value.ivalue= a.value.ivalue+b.value.ivalue;
- } else {
- ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
- }
- return ret;
- }
- static num num_mul(num a, num b) {
- num ret;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- if(ret.is_fixnum) {
- ret.value.ivalue= a.value.ivalue*b.value.ivalue;
- } else {
- ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
- }
- return ret;
- }
- static num num_div(num a, num b) {
- num ret;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
- if(ret.is_fixnum) {
- ret.value.ivalue= a.value.ivalue/b.value.ivalue;
- } else {
- ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
- }
- return ret;
- }
- static num num_intdiv(num a, num b) {
- num ret;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- if(ret.is_fixnum) {
- ret.value.ivalue= a.value.ivalue/b.value.ivalue;
- } else {
- ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
- }
- return ret;
- }
- static num num_sub(num a, num b) {
- num ret;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- if(ret.is_fixnum) {
- ret.value.ivalue= a.value.ivalue-b.value.ivalue;
- } else {
- ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
- }
- return ret;
- }
- static num num_rem(num a, num b) {
- num ret;
- long e1, e2, res;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- e1=num_ivalue(a);
- e2=num_ivalue(b);
- res=e1%e2;
- /* modulo should have same sign as second operand */
- if (res > 0) {
- if (e1 < 0) {
- res -= labs(e2);
- }
- } else if (res < 0) {
- if (e1 > 0) {
- res += labs(e2);
- }
- }
- ret.value.ivalue=res;
- return ret;
- }
- static num num_mod(num a, num b) {
- num ret;
- long e1, e2, res;
- ret.is_fixnum=a.is_fixnum && b.is_fixnum;
- e1=num_ivalue(a);
- e2=num_ivalue(b);
- res=e1%e2;
- if(res*e2<0) { /* modulo should have same sign as second operand */
- e2=labs(e2);
- if(res>0) {
- res-=e2;
- } else {
- res+=e2;
- }
- }
- ret.value.ivalue=res;
- return ret;
- }
- static int num_eq(num a, num b) {
- int ret;
- int is_fixnum=a.is_fixnum && b.is_fixnum;
- if(is_fixnum) {
- ret= a.value.ivalue==b.value.ivalue;
- } else {
- ret=num_rvalue(a)==num_rvalue(b);
- }
- return ret;
- }
- static int num_gt(num a, num b) {
- int ret;
- int is_fixnum=a.is_fixnum && b.is_fixnum;
- if(is_fixnum) {
- ret= a.value.ivalue>b.value.ivalue;
- } else {
- ret=num_rvalue(a)>num_rvalue(b);
- }
- return ret;
- }
- static int num_ge(num a, num b) {
- return !num_lt(a,b);
- }
- static int num_lt(num a, num b) {
- int ret;
- int is_fixnum=a.is_fixnum && b.is_fixnum;
- if(is_fixnum) {
- ret= a.value.ivalue<b.value.ivalue;
- } else {
- ret=num_rvalue(a)<num_rvalue(b);
- }
- return ret;
- }
- static int num_le(num a, num b) {
- return !num_gt(a,b);
- }
- #if USE_MATH
- /* Round to nearest. Round to even if midway */
- static double round_per_R5RS(double x) {
- double fl=floor(x);
- double ce=ceil(x);
- double dfl=x-fl;
- double dce=ce-x;
- if(dfl>dce) {
- return ce;
- } else if(dfl<dce) {
- return fl;
- } else {
- if(fmod(fl,2.0)==0.0) { /* I imagine this holds */
- return fl;
- } else {
- return ce;
- }
- }
- }
- #endif
- static int is_zero_double(double x) {
- return x<DBL_MIN && x>-DBL_MIN;
- }
- static long binary_decode(const char *s) {
- long x=0;
- while(*s!=0 && (*s=='1' || *s=='0')) {
- x<<=1;
- x+=*s-'0';
- s++;
- }
- return x;
- }
- /* allocate new cell segment */
- static int alloc_cellseg(scheme *sc, int n) {
- pointer newp;
- pointer last;
- pointer p;
- char *cp;
- long i;
- int k;
- int adj=ADJ;
- if(adj<sizeof(struct cell)) {
- adj=sizeof(struct cell);
- }
- for (k = 0; k < n; k++) {
- if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
- return k;
- cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
- if (cp == 0)
- return k;
- i = ++sc->last_cell_seg ;
- sc->alloc_seg[i] = cp;
- /* adjust in TYPE_BITS-bit boundary */
- if(((unsigned)cp)%adj!=0) {
- cp=(char*)(adj*((unsigned long)cp/adj+1));
- }
- /* insert new segment in address order */
- newp=(pointer)cp;
- sc->cell_seg[i] = newp;
- while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
- p = sc->cell_seg[i];
- sc->cell_seg[i] = sc->cell_seg[i - 1];
- sc->cell_seg[--i] = p;
- }
- sc->fcells += CELL_SEGSIZE;
- last = newp + CELL_SEGSIZE - 1;
- for (p = newp; p <= last; p++) {
- typeflag(p) = 0;
- cdr(p) = p + 1;
- car(p) = sc->NIL;
- }
- /* insert new cells in address order on free list */
- if (sc->free_cell == sc->NIL || p < sc->free_cell) {
- cdr(last) = sc->free_cell;
- sc->free_cell = newp;
- } else {
- p = sc->free_cell;
- while (cdr(p) != sc->NIL && newp > cdr(p))
- p = cdr(p);
- cdr(last) = cdr(p);
- cdr(p) = newp;
- }
- }
- return n;
- }
- static INLINE pointer get_cell(scheme *sc, pointer a, pointer b) {
- if (sc->free_cell != sc->NIL) {
- pointer x = sc->free_cell;
- sc->free_cell = cdr(x);
- --sc->fcells;
- return (x);
- }
- return _get_cell (sc, a, b);
- }
- /* get new cell. parameter a, b is marked by gc. */
- static pointer _get_cell(scheme *sc, pointer a, pointer b) {
- pointer x;
- if(sc->no_memory) {
- return sc->sink;
- }
-
- if (sc->free_cell == sc->NIL) {
- gc(sc,a, b);
- if (sc->fcells < sc->last_cell_seg*8
- || sc->free_cell == sc->NIL) {
- /* if only a few recovered, get more to avoid fruitless gc's */
- if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
- sc->no_memory=1;
- return sc->sink;
- }
- }
- }
- x = sc->free_cell;
- sc->free_cell = cdr(x);
- --sc->fcells;
- return (x);
- }
- /* make sure that there is a given number of cells free */
- static pointer reserve_cells(scheme *sc, int n) {
- if(sc->no_memory) {
- return sc->NIL;
- }
- /* Are there enough cells available? */
- if (sc->fcells < n) {
- /* If not, try gc'ing some */
- gc(sc, sc->NIL, sc->NIL);
- if (sc->fcells < n) {
- /* If there still aren't, try getting more heap */
- if (!alloc_cellseg(sc,1)) {
- sc->no_memory=1;
- return sc->NIL;
- }
- }
- if (sc->fcells < n) {
- /* If all fail, report failure */
- sc->no_memory=1;
- return sc->NIL;
- }
- }
- return (sc->T);
- }
- static pointer get_consecutive_cells(scheme *sc, int n) {
- pointer x;
- if(sc->no_memory) {
- return sc->sink;
- }
-
- /* Are there any cells available? */
- x=find_consecutive_cells(sc,n);
- if (x == sc->NIL) {
- /* If not, try gc'ing some */
- gc(sc, sc->NIL, sc->NIL);
- x=find_consecutive_cells(sc,n);
- if (x == sc->NIL) {
- /* If there still aren't, try getting more heap */
- if (!alloc_cellseg(sc,1)) {
- sc->no_memory=1;
- return sc->sink;
- }
- }
- x=find_consecutive_cells(sc,n);
- if (x == sc->NIL) {
- /* If all fail, report failure */
- sc->no_memory=1;
- return sc->sink;
- }
- }
- return (x);
- }
- static int count_consecutive_cells(pointer x, int needed) {
- int n=1;
- while(cdr(x)==x+1) {
- x=cdr(x);
- n++;
- if(n>needed) return n;
- }
- return n;
- }
- static pointer find_consecutive_cells(scheme *sc, int n) {
- pointer *pp;
- int cnt;
-
- pp=&sc->free_cell;
- while(*pp!=sc->NIL) {
- cnt=count_consecutive_cells(*pp,n);
- if(cnt>=n) {
- pointer x=*pp;
- *pp=cdr(*pp+n-1);
- sc->fcells -= n;
- return x;
- }
- pp=&cdr(*pp+cnt-1);
- }
- return sc->NIL;
- }
- /* get new cons cell */
- pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
- pointer x = get_cell(sc,a, b);
- typeflag(x) = T_PAIR;
- if(immutable) {
- setimmutable(x);
- }
- car(x) = a;
- cdr(x) = b;
- return (x);
- }
- /* ========== oblist implementation ========== */
- #ifndef USE_OBJECT_LIST
- static int hash_fn(const char *key, int table_size);
- static pointer oblist_initial_value(scheme *sc)
- {
- return mk_vector(sc, 461); /* probably should be bigger */
- }
- /* returns the new symbol */
- static pointer oblist_add_by_name(scheme *sc, const char *name)
- {
- pointer x;
- int location;
- x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
- typeflag(x) = T_SYMBOL;
- setimmutable(car(x));
- location = hash_fn(name, ivalue_unchecked(sc->oblist));
- set_vector_elem(sc->oblist, location,
- immutable_cons(sc, x, vector_elem(sc->oblist, location)));
- return x;
- }
- static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
- {
- int location;
- pointer x;
- char *s;
- location = hash_fn(name, ivalue_unchecked(sc->oblist));
- for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) {
- s = symname(car(x));
- /* case-insensitive, per R5RS section 2. */
- if(stricmp(name, s) == 0) {
- return car(x);
- }
- }
- return sc->NIL;
- }
- static pointer oblist_all_symbols(scheme *sc)
- {
- int i;
- pointer x;
- pointer ob_list = sc->NIL;
- for (i = 0; i < ivalue_unchecked(sc->oblist); i++) {
- for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
- ob_list = cons(sc, x, ob_list);
- }
- }
- return ob_list;
- }
- #else
- static pointer oblist_initial_value(scheme *sc)
- {
- return sc->NIL;
- }
- static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
- {
- pointer x;
- char *s;
- for (x = sc->oblist; x != sc->NIL; x = cdr(x)) {
- s = symname(car(x));
- /* case-insensitive, per R5RS section 2. */
- if(stricmp(name, s) == 0) {
- return car(x);
- }
- }
- return sc->NIL;
- }
- /* returns the new symbol */
- static pointer oblist_add_by_name(scheme *sc, const char *name)
- {
- pointer x;
- x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
- typeflag(x) = T_SYMBOL;
- setimmutable(car(x));
- sc->oblist = immutable_cons(sc, x, sc->oblist);
- return x;
- }
- static pointer oblist_all_symbols(scheme *sc)
- {
- return sc->oblist;
- }
- #endif
- static pointer mk_port(scheme *sc, port *p) {
- pointer x = get_cell(sc, sc->NIL, sc->NIL);
-
- typeflag(x) = T_PORT|T_ATOM;
- x->_object._port=p;
- return (x);
- }
- pointer mk_foreign_func(scheme *sc, foreign_func f) {
- pointer x = get_cell(sc, sc->NIL, sc->NIL);
-
- typeflag(x) = (T_FOREIGN | T_ATOM);
- x->_object._ff=f;
- return (x);
- }
- INTERFACE pointer mk_character(scheme *sc, int c) {
- pointer x = get_cell(sc,sc->NIL, sc->NIL);
- typeflag(x) = (T_CHARACTER | T_ATOM);
- ivalue_unchecked(x)= c;
- set_integer(x);
- return (x);
- }
- /* get number atom (integer) */
- INTERFACE pointer mk_integer(scheme *sc, long num) {
- pointer x = get_cell(sc,sc->NIL, sc->NIL);
- typeflag(x) = (T_NUMBER | T_ATOM);
- ivalue_unchecked(x)= num;
- set_integer(x);
- return (x);
- }
- INTERFACE pointer mk_real(scheme *sc, double n) {
- pointer x = get_cell(sc,sc->NIL, sc->NIL);
- typeflag(x) = (T_NUMBER | T_ATOM);
- rvalue_unchecked(x)= n;
- set_real(x);
- return (x);
- }
- static pointer mk_number(scheme *sc, num n) {
- if(n.is_fixnum) {
- return mk_integer(sc,n.value.ivalue);
- } else {
- return mk_real(sc,n.value.rvalue);
- }
- }
- /* allocate name to string area */
- static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
- char *q;
-
- q=(char*)sc->malloc(len_str+1);
- if(q==0) {
- sc->no_memory=1;
- return sc->strbuff;
- }
- if(str!=0) {
- strcpy(q, str);
- } else {
- memset(q, fill, len_str);
- q[len_str]=0;
- }
- return (q);
- }
- /* get new string */
- INTERFACE pointer mk_string(scheme *sc, const char *str) {
- return mk_counted_string(sc,str,strlen(str));
- }
- INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
- pointer x = get_cell(sc, sc->NIL, sc->NIL);
- strvalue(x) = store_string(sc,len,str,0);
- typeflag(x) = (T_STRING | T_ATOM);
- strlength(x) = len;
- return (x);
- }
- static pointer mk_empty_string(scheme *sc, int len, char fill) {
- pointer x = get_cell(sc, sc->NIL, sc->NIL);
- strvalue(x) = store_string(sc,len,0,fill);
- typeflag(x) = (T_STRING | T_ATOM);
- strlength(x) = len;
- return (x);
- }
- INTERFACE static pointer mk_vector(scheme *sc, int len) {
- pointer x=get_consecutive_cells(sc,len/2+len%2+1);
- typeflag(x) = (T_VECTOR | T_ATOM);
- ivalue_unchecked(x)=len;
- set_integer(x);
- fill_vector(x,sc->NIL);
- return x;
- }
- INTERFACE static void fill_vector(pointer vec, pointer obj) {
- int i;
- int num=ivalue(vec)/2+ivalue(vec)%2;
- for(i=0; i<num; i++) {
- typeflag(vec+1+i) = T_PAIR;
- setimmutable(vec+1+i);
- car(vec+1+i)=obj;
- cdr(vec+1+i)=obj;
- }
- }
- INTERFACE static pointer vector_elem(pointer vec, int ielem) {
- int n=ielem/2;
- if(ielem%2==0) {
- return car(vec+1+n);
- } else {
- return cdr(vec+1+n);
- }
- }
- INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
- int n=ielem/2;
- if(ielem%2==0) {
- return car(vec+1+n)=a;
- } else {
- return cdr(vec+1+n)=a;
- }
- }
- /* get new symbol */
- INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
- pointer x;
- /* first check oblist */
- x = oblist_find_by_name(sc, name);
- if (x != sc->NIL) {
- return (x);
- } else {
- x = oblist_add_by_name(sc, name);
- return (x);
- }
- }
- INTERFACE pointer gensym(scheme *sc) {
- pointer x;
- char name[40];
- for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
- sprintf(name,"gensym-%ld",sc->gensym_cnt);
- /* first check oblist */
- x = oblist_find_by_name(sc, name);
- if (x != sc->NIL) {
- continue;
- } else {
- x = oblist_add_by_name(sc, name);
- return (x);
- }
- }
- return sc->NIL;
- }
- /* make symbol or number atom from string */
- static pointer mk_atom(scheme *sc, char *q) {
- char c, *p;
- int has_dec_point=0;
- int has_fp_exp = 0;
- #if USE_COLON_HOOK
- if((p=strstr(q,"::"))!=0) {
- *p=0;
- return cons(sc, sc->COLON_HOOK,
- cons(sc,
- cons(sc,
- sc->QUOTE,
- cons(sc, mk_atom(sc,p+2), sc->NIL)),
- cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
- }
- #endif
- p = q;
- c = *p++;
- if ((c == '+') || (c == '-')) {
- c = *p++;
- if (c == '.') {
- has_dec_point=1;
- c = *p++;
- }
- if (!isdigit(c)) {
- return (mk_symbol(sc, strlwr(q)));
- }
- } else if (c == '.') {
- has_dec_point=1;
- c = *p++;
- if (!isdigit(c)) {
- return (mk_symbol(sc, strlwr(q)));
- }
- } else if (!isdigit(c)) {
- return (mk_symbol(sc, strlwr(q)));
- }
- for ( ; (c = *p) != 0; ++p) {
- if (!isdigit(c)) {
- if(c=='.') {
- if(!has_dec_point) {
- has_dec_point=1;
- continue;
- }
- }
- else if ((c == 'e') || (c == 'E')) {
- if(!has_fp_exp) {
- has_dec_point = 1; /* decimal point illegal
- from now on */
- p++;
- if ((*p == '-') || (*p == '+') || isdigit(*p)) {
- continue;
- }
- }
- }
- return (mk_symbol(sc, strlwr(q)));
- }
- }
- if(has_dec_point) {
- return mk_real(sc,atof(q));
- }
- return (mk_integer(sc, atol(q)));
- }
- /* make constant */
- static pointer mk_sharp_const(scheme *sc, char *name) {
- long x;
- char tmp[256];
- if (!strcmp(name, "t"))
- return (sc->T);
- else if (!strcmp(name, "f"))
- return (sc->F);
- else if (*name == 'o') {/* #o (octal) */
- snprintf(tmp, sizeof(tmp), "0%s", name+1);
- sscanf(tmp, "%lo", &x);
- return (mk_integer(sc, x));
- } else if (*name == 'd') { /* #d (decimal) */
- sscanf(name+1, "%ld", &x);
- return (mk_integer(sc, x));
- } else if (*name == 'x') { /* #x (hex) */
- snprintf(tmp, sizeof(tmp), "0x%s", name+1);
- sscanf(tmp, "%lx", &x);
- return (mk_integer(sc, x));
- } else if (*name == 'b') { /* #b (binary) */
- x = binary_decode(name+1);
- return (mk_integer(sc, x));
- } else if (*name == '\\') { /* #\w (character) */
- int c=0;
- if(stricmp(name+1,"space")==0) {
- c=' ';
- } else if(stricmp(name+1,"newline")==0) {
- c='\n';
- } else if(stricmp(name+1,"return")==0) {
- c='\r';
- } else if(stricmp(name+1,"tab")==0) {
- c='\t';
- } else if(name[1]=='x' && name[2]!=0) {
- int c1=0;
- if(sscanf(name+2,"%x",&c1)==1 && c1<256) {
- c=c1;
- } else {
- return sc->NIL;
- }
- #if USE_ASCII_NAMES
- } else if(is_ascii_name(name+1,&c)) {
- /* nothing */
- #endif
- } else if(name[2]==0) {
- c=name[1];
- } else {
- return sc->NIL;
- }
- return mk_character(sc,c);
- } else
- return (sc->NIL);
- }
- /* ========== garbage collector ========== */
- /*--
- * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
- * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
- * for marking.
- */
- static void mark(pointer a) {
- pointer t, q, p;
- t = (pointer) 0;
- p = a;
- E2: setmark(p);
- if(is_vector(p)) {
- int i;
- int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
- for(i=0; i<num; i++) {
- /* Vector cells will be treated like ordinary cells */
- mark(p+1+i);
- }
- }
- if (is_atom(p))
- goto E6;
- /* E4: down car */
- q = car(p);
- if (q && !is_mark(q)) {
- setatom(p); /* a note that we have moved car */
- car(p) = t;
- t = p;
- p = q;
- goto E2;
- }
- E5: q = cdr(p); /* down cdr */
- if (q && !is_mark(q)) {
- cdr(p) = t;
- t = p;
- p = q;
- goto E2;
- }
- E6: /* up. Undo the link switching from steps E4 and E5. */
- if (!t)
- return;
- q = t;
- if (is_atom(q)) {
- clratom(q);
- t = car(q);
- car(q) = p;
- p = q;
- goto E5;
- } else {
- t = cdr(q);
- cdr(q) = p;
- p = q;
- goto E6;
- }
- }
- /* garbage collection. parameter a, b is marked. */
- static void gc(scheme *sc, pointer a, pointer b) {
- pointer p;
- int i;
-
- if(sc->gc_verbose) {
- putstr(sc, "gc...");
- }
- /* mark system globals */
- mark(sc->oblist);
- mark(sc->global_env);
- /* mark current registers */
- mark(sc->args);
- mark(sc->envir);
- mark(sc->code);
- dump_stack_mark(sc);
- mark(sc->value);
- mark(sc->inport);
- mark(sc->save_inport);
- mark(sc->outport);
- mark(sc->loadport);
- /* mark variables a, b */
- mark(a);
- mark(b);
- /* garbage collect */
- clrmark(sc->NIL);
- sc->fcells = 0;
- sc->free_cell = sc->NIL;
- /* free-list is kept sorted by address so as to maintain consecutive
- ranges, if possible, for use with vectors. Here we scan the cells
- (which are also kept sorted by address) downwards to build the
- free-list in sorted order.
- */
- for (i = sc->last_cell_seg; i >= 0; i--) {
- p = sc->cell_seg[i] + CELL_SEGSIZE;
- while (--p >= sc->cell_seg[i]) {
- if (is_mark(p)) {
- clrmark(p);
- } else {
- /* reclaim cell */
- if (typeflag(p) != 0) {
- finalize_cell(sc, p);
- typeflag(p) = 0;
- car(p) = sc->NIL;
- }
- ++sc->fcells;
- cdr(p) = sc->free_cell;
- sc->free_cell = p;
- }
- }
- }
-
- if (sc->gc_verbose) {
- char msg[80];
- sprintf(msg,"done: %ld cells were recovered.\n", sc->fcells);
- putstr(sc,msg);
- }
- }
- static void finalize_cell(scheme *sc, pointer a) {
- if(is_string(a)) {
- sc->free(strvalue(a));
- } else if(is_port(a)) {
- if(a->_object._port->kind&port_file
- && a->_object._port->rep.stdio.closeit) {
- port_close(sc,a,port_input|port_output);
- }
- sc->free(a->_object._port);
- }
- }
- /* ========== Routines for Reading ========== */
- static int file_push(scheme *sc, const char *fname) {
- FILE *fin=fopen(fname,"r");
- if(fin!=0) {
- sc->file_i++;
- sc->load_stack[sc->file_i].kind=port_file|port_input;
- sc->load_stack[sc->file_i].rep.stdio.file=fin;
- sc->load_stack[sc->file_i].rep.stdio.closeit=1;
- sc->nesting_stack[sc->file_i]=0;
- sc->loadport->_object._port=sc->load_stack+sc->file_i;
- }
- return fin!=0;
- }
- static void file_pop(scheme *sc) {
- sc->nesting=sc->nesting_stack[sc->file_i];
- if(sc->file_i!=0) {
- port_close(sc,sc->loadport,port_input);
- sc->file_i--;
- sc->loadport->_object._port=sc->load_stack+sc->file_i;
- if(file_interactive(sc)) {
- putstr(sc,prompt);
- }
- }
- }
- static int file_interactive(scheme *sc) {
- return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
- && sc->inport->_object._port->kind&port_file;
- }
- static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
- FILE *f;
- char *rw;
- port *pt;
- if(prop==(port_input|port_output)) {
- rw="a+";
- } else if(prop==port_output) {
- rw="w";
- } else {
- rw="r";
- }
- f=fopen(fn,rw);
- if(f==0) {
- return 0;
- }
- pt=port_rep_from_file(sc,f,prop);
- pt->rep.stdio.closeit=1;
- return pt;
- }
- static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
- port *pt;
- pt=port_rep_from_filename(sc,fn,prop);
- if(pt==0) {
- return sc->NIL;
- }
- return mk_port(sc,pt);
- }
- static port *port_rep_from_file(scheme *sc, FILE *f, int prop) {
- char *rw;
- port *pt;
- pt=(port*)sc->malloc(sizeof(port));
- if(pt==0) {
- return 0;
- }
- if(prop==(port_input|port_output)) {
- rw="a+";
- } else if(prop==port_output) {
- rw="w";
- } else {
- rw="r";
- }
- pt->kind=port_file|prop;
- pt->rep.stdio.file=f;
- pt->rep.stdio.closeit=0;
- return pt;
- }
- static pointer port_from_file(scheme *sc, FILE *f, int prop) {
- port *pt;
- pt=port_rep_from_file(sc,f,prop);
- if(pt==0) {
- return sc->NIL;
- }
- return mk_port(sc,pt);
- }
- static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
- port *pt;
- pt=(port*)sc->malloc(sizeof(port));
- if(pt==0) {
- return 0;
- }
- pt->kind=port_string|prop;
- pt->rep.string.start=start;
- pt->rep.string.curr=start;
- pt->rep.string.past_the_end=past_the_end;
- return pt;
- }
- static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
- port *pt;
- pt=port_rep_from_string(sc,start,past_the_end,prop);
- if(pt==0) {
- return sc->NIL;
- }
- return mk_port(sc,pt);
- }
- static void port_close(scheme *sc, pointer p, int flag) {
- port *pt=p->_object._port;
- pt->kind&=~flag;
- if((pt->kind & (port_input|port_output))==0) {
- if(pt->kind&port_file) {
- fclose(pt->rep.stdio.file);
- }
- pt->kind=port_free;
- }
- }
- /* get new character from input file */
- static int inchar(scheme *sc) {
- int c;
- port *pt;
- again:
- pt=sc->inport->_object._port;
- c=basic_inchar(pt);
- if(c==EOF && sc->inport==sc->loadport && sc->file_i!=0) {
- file_pop(sc);
- if(sc->nesting!=0) {
- return EOF;
- } else {
- return '\n';
- }
- goto again;
- }
- return c;
- }
- static int basic_inchar(port *pt) {
- if(pt->kind&port_file) {
- return fgetc(pt->rep.stdio.file);
- } else {
- if(*pt->rep.string.curr==0
- || pt->rep.string.curr==pt->rep.string.past_the_end) {
- return EOF;
- } else {
- return *pt->rep.string.curr++;
- }
- }
- }
- /* back character to input buffer */
- static void backchar(scheme *sc, int c) {
- port *pt;
- if(c==EOF) return;
- pt=sc->inport->_object._port;
- if(pt->kind&port_file) {
- ungetc(c,pt->rep.stdio.file);
- } else {
- if(pt->rep.string.curr!=pt->rep.string.start) {
- --pt->rep.string.curr;
- }
- }
- }
- INTERFACE void putstr(scheme *sc, const char *s) {
- port *pt=sc->outport->_object._port;
- if(pt->kind&port_file) {
- fputs(s,pt->rep.stdio.file);
- } else {
- for(;*s;s++) {
- if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
- *pt->rep.string.curr++=*s;
- }
- }
- }
- }
- static void putchars(scheme *sc, const char *s, int len) {
- port *pt=sc->outport->_object._port;
- if(pt->kind&port_file) {
- fwrite(s,1,len,pt->rep.stdio.file);
- } else {
- for(;len;len--) {
- if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
- *pt->rep.string.curr++=*s++;
- }
- }
- }
- }
- INTERFACE void putcharacter(scheme *sc, int c) {
- port *pt=sc->outport->_object._port;
- if(pt->kind&port_file) {
- fputc(c,pt->rep.stdio.file);
- } else {
- if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
- *pt->rep.string.curr++=c;
- }
- }
- }
- /* read characters up to delimiter, but cater to character constants */
- static char *readstr_upto(scheme *sc, char *delim) {
- char *p = sc->strbuff;
- while (!is_one_of(delim, (*p++ = inchar(sc))));
- if(p==sc->strbuff+2 && p[-2]=='\\') {
- *p=0;
- } else {
- backchar(sc,p[-1]);
- *--p = '\0';
- }
- return sc->strbuff;
- }
- /* read string expression "xxx...xxx" */
- static pointer readstrexp(scheme *sc) {
- char *p = sc->strbuff;
- int c;
- int c1=0;
- enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2, st_oct3 } state=st_ok;
-
- for (;;) {
- c=inchar(sc);
- if(c==EOF || p-sc->strbuff>sizeof(sc->strbuff)-1) {
- return sc->F;
- }
- switch(state) {
- case st_ok:
- switch(c) {
- case '\\':
- state=st_bsl;
- break;
- case '"':
- *p=0;
- return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
- default:
- *p++=c;
- break;
- }
- break;
- case st_bsl:
- switch(c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- state=st_oct1;
- c1=c-'0';
- break;
- case 'x':
- case 'X':
- state=st_x1;
- c1=0;
- break;
- case 'n':
- *p++='\n';
- state=st_ok;
- break;
- case 't':
- *p++='\t';
- state=st_ok;
- break;
- case 'r':
- *p++='\r';
- state=st_ok;
- break;
- case '"':
- *p++='"';
- state=st_ok;
- break;
- default:
- *p++=c;
- state=st_ok;
- break;
- }
- break;
- case st_x1:
- case st_x2:
- c=toupper(c);
- if(c>='0' && c<='F') {
- if(c<='9') {
- c1=(c1<<4)+c-'0';
- } else {
- c1=(c1<<4)+c-'A'+10;
- }
- if(state==st_x1) {
- state=st_x2;
- } else {
- *p++=c1;
- state=st_ok;
- }
- } else {
- return sc->F;
- }
- break;
- case st_oct1:
- case st_oct2:
- case st_oct3:
- if (c < '0' || c > '7')
- {
- if (state==st_oct1)
- return sc->F;
- *p++=c1;
- backchar(sc, c);
- state=st_ok;
- }
- else
- {
- c1=(c1<<3)+(c-'0');
- switch (state)
- {
- case st_oct1:
- state=st_oct2;
- break;
- case st_oct2:
- state=st_oct3;
- break;
- default:
- *p++=c1;
- state=st_ok;
- break;
- }
- }
- break;
- }
- }
- }
- /* check c is in chars */
- static INLINE int is_one_of(char *s, int c) {
- if(c==EOF) return 1;
- while (*s)
- if (*s++ == c)
- return (1);
- return (0);
- }
- /* skip white characters */
- static INLINE void skipspace(scheme *sc) {
- int c;
- while (isspace(c=inchar(sc)))
- ;
- if(c!=EOF) {
- backchar(sc,c);
- }
- }
- /* get token */
- static int token(scheme *sc) {
- int c;
- skipspace(sc);
- switch (c=inchar(sc)) {
- case EOF:
- return (TOK_EOF);
- case '(':
- return (TOK_LPAREN);
- case ')':
- return (TOK_RPAREN);
- case '.':
- c=inchar(sc);
- if(is_one_of(" \n\t",c)) {
- return (TOK_DOT);
- } else {
- backchar(sc,c);
- backchar(sc,'.');
- return TOK_ATOM;
- }
- case '\'':
- return (TOK_QUOTE);
- case ';':
- while ((c=inchar(sc)) != '\n' && c!=EOF)
- ;
- return (token(sc));
- case '"':
- return (TOK_DQUOTE);
- case BACKQUOTE:
- return (TOK_BQUOTE);
- case ',':
- if ((c=inchar(sc)) == '@') {
- return (TOK_ATMARK);
- } else {
- backchar(sc,c);
- return (TOK_COMMA);
- }
- case '#':
- c=inchar(sc);
- if (c == '(') {
- return (TOK_VEC);
- } else if(c == '!') {
- while ((c=inchar(sc)) != '\n' && c!=EOF)
- ;
- return (token(sc));
- } else {
- backchar(sc,c);
- if(is_one_of(" tfodxb\\",c)) {
- return TOK_SHARP_CONST;
- } else {
- return (TOK_SHARP);
- }
- }
- default:
- backchar(sc,c);
- return (TOK_ATOM);
- }
- }
- /* ========== Routines for Printing ========== */
- #define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL)
- static void printslashstring(scheme *sc, char *p, int len) {
- int i;
- unsigned char *s=(unsigned char*)p;
- putcharacter(sc,'"');
- for ( i=0; i<len; i++) {
- if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
- putcharacter(sc,'\\');
- switch(*s) {
- case '"':
- putcharacter(sc,'"');
- break;
- case '\n':
- putcharacter(sc,'n');
- break;
- case '\t':
- putcharacter(sc,'t');
- break;
- case '\r':
- putcharacter(sc,'r');
- break;
- case '\\':
- putcharacter(sc,'\\');
- break;
- default: {
- int d=*s/16;
- putcharacter(sc,'x');
- if(d<10) {
- putcharacter(sc,d+'0');
- } else {
- putcharacter(sc,d-10+'A');
- }
- d=*s%16;
- if(d<10) {
- putcharacter(sc,d+'0');
- } else {
- putcharacter(sc,d-10+'A');
- }
- }
- }
- } else {
- putcharacter(sc,*s);
- }
- s++;
- }
- putcharacter(sc,'"');
- }
- /* print atoms */
- static void printatom(scheme *sc, pointer l, int f) {
- char *p;
- int len;
- atom2str(sc,l,f,&p,&len);
- putchars(sc,p,len);
- }
- /* Uses internal buffer unless string pointer is already available */
- static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) {
- char *p;
- if (l == sc->NIL) {
- p = "()";
- } else if (l == sc->T) {
- p = "#t";
- } else if (l == sc->F) {
- p = "#f";
- } else if (l == sc->EOF_OBJ) {
- p = "#<EOF>";
- } else if (is_port(l)) {
- p = sc->strbuff;
- strcpy(p, "#<PORT>");
- } else if (is_number(l)) {
- p = sc->strbuff;
- if(is_integer(l)) {
- sprintf(p, "%ld", ivalue_unchecked(l));
- } else {
- sprintf(p, "%.10g", rvalue_unchecked(l));
- }
- } else if (is_string(l)) {
- if (!f) {
- p = strvalue(l);
- } else { /* Hack, uses the fact that printing is needed */
- *pp=sc->strbuff;
- *plen=0;
- printslashstring(sc, strvalue(l), strlength(l));
- return;
- }
- } else if (is_character(l)) {
- int c=charvalue(l);
- p = sc->strbuff;
- if (!f) {
- p[0]=c;
- p[1]=0;
- } else {
- switch(c) {
- case ' ':
- sprintf(p,"#\\space"); break;
- case '\n':
- sprintf(p,"#\\newline"); break;
- case '\r':
- sprintf(p,"#\\return"); break;
- case '\t':
- sprintf(p,"#\\tab"); break;
- default:
- #if USE_ASCII_NAMES
- if(c==127) {
- strcpy(p,"#\\del"); break;
- } else if(c<32) {
- strcpy(p,"#\\"); strcat(p,charnames[c]); break;
- }
- #else
- if(c<32) {
- sprintf(p,"#\\x%x",c); break;
- }
- #endif
- sprintf(p,"#\\%c",c); break;
- }
- }
- } else if (is_symbol(l)) {
- p = symname(l);
- } else if (is_proc(l)) {
- p = sc->strbuff;
- sprintf(p, "#<%s PROCEDURE %ld>", procname(l),procnum(l));
- } else if (is_macro(l)) {
- p = "#<MACRO>";
- } else if (is_closure(l)) {
- p = "#<CLOSURE>";
- } else if (is_promise(l)) {
- p = "#<PROMISE>";
- } else if (is_foreign(l)) {
- p = sc->strbuff;
- sprintf(p, "#<FOREIGN PROCEDURE %ld>", procnum(l));
- } else if (is_continuation(l)) {
- p = "#<CONTINUATION>";
- } else {
- p = "#<ERROR>";
- }
- *pp=p;
- *plen=strlen(p);
- }
- /* ========== Routines for Evaluation Cycle ========== */
- /* make closure. c is code. e is environment */
- static pointer mk_closure(scheme *sc, pointer c, pointer e) {
- pointer x = get_cell(sc, c, e);
- typeflag(x) = T_CLOSURE;
- car(x) = c;
- cdr(x) = e;
- return (x);
- }
- /* make continuation. */
- static pointer mk_continuation(scheme *sc, pointer d) {
- pointer x = get_cell(sc, sc->NIL, d);
- typeflag(x) = T_CONTINUATION;
- cont_dump(x) = d;
- return (x);
- }
- static pointer list_star(scheme *sc, pointer d) {
- pointer p, q;
- if(cdr(d)==sc->NIL) {
- return car(d);
- }
- p=cons(sc,car(d),cdr(d));
- q=p;
- while(cdr(cdr(p))!=sc->NIL) {
- d=cons(sc,car(p),cdr(p));
- if(cdr(cdr(p))!=sc->NIL) {
- p=cdr(d);
- }
- }
- cdr(p)=car(cdr(p));
- return q;
- }
- /* reverse list -- produce new list */
- static pointer reverse(scheme *sc, pointer a) {
- /* a must be checked by gc */
- pointer p = sc->NIL;
- for ( ; is_pair(a); a = cdr(a)) {
- p = cons(sc, car(a), p);
- }
- return (p);
- }
- /* reverse list --- in-place */
- static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
- pointer p = list, result = term, q;
- while (p != sc->NIL) {
- q = cdr(p);
- cdr(p) = result;
- result = p;
- p = q;
- }
- return (result);
- }
- /* append list -- produce new list */
- static pointer append(scheme *sc, pointer a, pointer b) {
- pointer p = b, q;
- if (a != sc->NIL) {
- a = reverse(sc, a);
- while (a != sc->NIL) {
- q = cdr(a);
- cdr(a) = p;
- p = a;
- a = q;
- }
- }
- return (p);
- }
- /* equivalence of atoms */
- static int eqv(pointer a, pointer b) {
- if (is_string(a)) {
- if (is_string(b))
- return (strvalue(a) == strvalue(b));
- else
- return (0);
- } else if (is_number(a)) {
- if (is_number(b))
- return num_eq(nvalue(a),nvalue(b));
- else
- return (0);
- } else if (is_character(a)) {
- if (is_character(b))
- return charvalue(a)==charvalue(b);
- else
- return (0);
- } else if (is_port(a)) {
- if (is_port(b))
- return a==b;
- else
- return (0);
- } else if (is_proc(a)) {
- if (is_proc(b))
- return procnum(a)==procnum(b);
- else
- return (0);
- } else {
- return (a == b);
- }
- }
- /* true or false value macro */
- /* () is #t in R5RS */
- #define is_true(p) ((p) != sc->F)
- #define is_false(p) ((p) == sc->F)
- /* ========== Environment implementation ========== */
- #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
- static int hash_fn(const char *key, int table_size)
- {
- unsigned int hashed = 0;
- const char *c;
- int bits_per_int = sizeof(unsigned int)*8;
- for (c = key; *c; c++) {
- /* letters have about 5 bits in them */
- hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
- hashed ^= *c;
- }
- return hashed % table_size;
- }
- #endif
- #ifndef USE_ALIST_ENV
- /*
- * In this implementation, each frame of the environment may be
- * a hash table: a vector of alists hashed by variable name.
- * In practice, we use a vector only for the initial frame;
- * subsequent frames are too small and transient for the lookup
- * speed to out-weigh the cost of making a new vector.
- */
- static void new_frame_in_env(scheme *sc, pointer old_env)
- {
- pointer new_frame;
- /* The interaction-environment has about 300 variables in it. */
- if (old_env == sc->NIL) {
- new_frame = mk_vector(sc, 461);
- } else {
- new_frame = sc->NIL;
- }
- sc->envir = immutable_cons(sc, new_frame, old_env);
- setenvironment(sc->envir);
- }
- static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
- pointer variable, pointer value)
- {
- pointer slot = immutable_cons(sc, variable, value);
- if (is_vector(car(env))) {
- int location = hash_fn(symname(variable), ivalue_unchecked(car(env)));
- set_vector_elem(car(env), location,
- immutable_cons(sc, slot, vector_elem(car(env), location)));
- } else {
- car(env) = immutable_cons(sc, slot, car(env));
- }
- }
- static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
- {
- pointer x,y;
- int location;
- for (x = env; x != sc->NIL; x = cdr(x)) {
- if (is_vector(car(x))) {
- location = hash_fn(symname(hdl), ivalue_unchecked(car(x)));
- y = vector_elem(car(x), location);
- } else {
- y = car(x);
- }
- for ( ; y != sc->NIL; y = cdr(y)) {
- if (caar(y) == hdl) {
- break;
- }
- }
- if (y != sc->NIL) {
- break;
- }
- if(!all) {
- return sc->NIL;
- }
- }
- if (x != sc->NIL) {
- return car(y);
- }
- return sc->NIL;
- }
- #else /* USE_ALIST_ENV */
- static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
- {
- sc->envir = immutable_cons(sc, sc->NIL, old_env);
- setenvironment(sc->envir);
- }
- static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
- pointer variable, pointer value)
- {
- car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env));
- }
- static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
- {
- pointer x,y;
- for (x = env; x != sc->NIL; x = cdr(x)) {
- for (y = car(x); y != sc->NIL; y = cdr(y)) {
- if (caar(y) == hdl) {
- break;
- }
- }
- if (y != sc->NIL) {
- break;
- }
- if(!all) {
- return sc->NIL;
- }
- }
- if (x != sc->NIL) {
- return car(y);
- }
- return sc->NIL;
- }
- #endif /* USE_ALIST_ENV else */
- static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
- {
- new_slot_spec_in_env(sc, sc->envir, variable, value);
- }
- static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
- {
- cdr(slot) = value;
- }
- static INLINE pointer slot_value_in_env(pointer slot)
- {
- return cdr(slot);
- }
- /* ========== Evaluation Cycle ========== */
- static pointer _Error_1(scheme *sc, const char *s, pointer a) {
- #if USE_ERROR_HOOK
- pointer x;
- pointer hdl=sc->ERROR_HOOK;
- x=find_slot_in_env(sc,sc->envir,hdl,1);
- if (x != sc->NIL) {
- if(a!=0) {
- sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
- } else {
- sc->code = sc->NIL;
- }
- sc->code = cons(sc, mk_string(sc, (s)), sc->code);
- setimmutable(car(sc->code));
- sc->code = cons(sc, slot_value_in_env(x), sc->code);
- sc->op = (int)OP_EVAL;
- return sc->T;
- }
- #endif
- if(a!=0) {
- sc->args = cons(sc, (a), sc->NIL);
- } else {
- sc->args = sc->NIL;
- }
- sc->args = cons(sc, mk_string(sc, (s)), sc->args);
- setimmutable(car(sc->args));
- sc->op = (int)OP_ERR0;
- return sc->T;
- }
- #define Error_1(sc,s, a) return _Error_1(sc,s,a)
- #define Error_0(sc,s) return _Error_1(sc,s,0)
- /* Too small to turn into function */
- # define BEGIN do {
- # define END } while (0)
- #define s_goto(sc,a) BEGIN \
- sc->op = (int)(a); \
- return sc->T; END
- #define s_return(sc,a) return _s_return(sc,a)
- #ifndef USE_SCHEME_STACK
- /* this structure holds all the interpreter's registers */
- struct dump_stack_frame {
- enum scheme_opcodes op;
- pointer args;
- pointer envir;
- pointer code;
- };
- #define STACK_GROWTH 3
- static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code)
- {
- int nframes = (int)sc->dump;
- struct dump_stack_frame *next_frame;
- /* enough room for the next frame? */
- if (nframes >= sc->dump_size) {
- sc->dump_size += STACK_GROWTH;
- /* alas there is no sc->realloc */
- sc->dump_base = realloc(sc->dump_base,
- sizeof(struct dump_stack_frame) * sc->dump_size);
- }
- next_frame = (struct dump_stack_frame *)sc->dump_base + nframes;
- next_frame->op = op;
- next_frame->args = args;
- next_frame->envir = sc->envir;
- next_frame->code = code;
- sc->dump = (pointer)(nframes+1);
- }
- static pointer _s_return(scheme *sc, pointer a)
- {
- int nframes = (int)sc->dump;
- struct dump_stack_frame *frame;
- sc->value = (a);
- if (nframes <= 0) {
- return sc->NIL;
- }
- nframes--;
- frame = (struct dump_stack_frame *)sc->dump_base + nframes;
- sc->op = frame->op;
- sc->args = frame->args;
- sc->envir = frame->envir;
- sc->code = frame->code;
- sc->dump = (pointer)nframes;
- return sc->T;
- }
- static INLINE void dump_stack_reset(scheme *sc)
- {
- /* in this implementation, sc->dump is the number of frames on the stack */
- sc->dump = (pointer)0;
- }
- static INLINE void dump_stack_initialize(scheme *sc)
- {
- sc->dump_size = 0;
- sc->dump_base = NULL;
- dump_stack_reset(sc);
- }
- static void dump_stack_free(scheme *sc)
- {
- free(sc->dump_base);
- sc->dump_base = NULL;
- sc->dump = (pointer)0;
- sc->dump_size = 0;
- }
- static INLINE void dump_stack_mark(scheme *sc)
- {
- int nframes = (int)sc->dump;
- int i;
- for(i=0; i<nframes; i++) {
- struct dump_stack_frame *frame;
- frame = (struct dump_stack_frame *)sc->dump_base + i;
- mark(frame->args);
- mark(frame->envir);
- mark(frame->code);
- }
- }
- #else
- static INLINE void dump_stack_reset(scheme *sc)
- {
- sc->dump = sc->NIL;
- }
- static INLINE void dump_stack_initialize(scheme *sc)
- {
- dump_stack_reset(sc);
- }
- static void dump_stack_free(scheme *sc)
- {
- sc->dump = sc->NIL;
- }
- static pointer _s_return(scheme *sc, pointer a) {
- sc->value = (a);
- if(sc->dump==sc->NIL) return sc->NIL;
- sc->op = ivalue(car(sc->dump));
- sc->args = cadr(sc->dump);
- sc->envir = caddr(sc->dump);
- sc->code = cadddr(sc->dump);
- sc->dump = cddddr(sc->dump);
- return sc->T;
- }
- static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
- sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
- sc->dump = cons(sc, (args), sc->dump);
- sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump);
- }
- static INLINE void dump_stack_mark(scheme *sc)
- {
- mark(sc->dump);
- }
- #endif
- #define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F)
- static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
- pointer x, y;
- switch (op) {
- case OP_LOAD: /* load */
- if(file_interactive(sc)) {
- fprintf(sc->outport->_object._port->rep.stdio.file,
- "Loading %s\n", strvalue(car(sc->args)));
- }
- if (!file_push(sc,strvalue(car(sc->args)))) {
- Error_1(sc,"unable to open", car(sc->args));
- }
- s_goto(sc,OP_T0LVL);
- case OP_T0LVL: /* top level */
- if(file_interactive(sc)) {
- putstr(sc,"\n");
- }
- sc->nesting=0;
- dump_stack_reset(sc);
- sc->envir = sc->global_env;
- sc->save_inport=sc->inport;
- sc->inport = sc->loadport;
- s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
- s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
- s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
- if (file_interactive(sc)) {
- putstr(sc,prompt);
- }
- s_goto(sc,OP_READ_INTERNAL);
- case OP_T1LVL: /* top level */
- sc->code = sc->value;
- sc->inport=sc->save_inport;
- s_goto(sc,OP_EVAL);
- case OP_READ_INTERNAL: /* internal read */
- sc->tok = token(sc);
- if(sc->tok==TOK_EOF) {
- if(sc->inport==sc->loadport) {
- sc->args=sc->NIL;
- s_goto(sc,OP_QUIT);
- } else {
- s_return(sc,sc->EOF_OBJ);
- }
- }
- s_goto(sc,OP_RDSEXPR);
- case OP_GENSYM:
- s_return(sc, gensym(sc));
- case OP_VALUEPRINT: /* print evaluation result */
- /* OP_VALUEPRINT is always pushed, because when changing from
- non-interactive to interactive mode, it needs to be
- already on the stack */
- if(sc->tracing) {
- putstr(sc,"\nGives: ");
- }
- if(file_interactive(sc)) {
- sc->print_flag = 1;
- sc->args = sc->value;
- s_goto(sc,OP_P0LIST);
- } else {
- s_return(sc,sc->value);
- }
- case OP_EVAL: /* main part of evaluation */
- #if USE_TRACING
- if(sc->tracing) {
- /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
- s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
- sc->args=sc->code;
- putstr(sc,"\nEval: ");
- s_goto(sc,OP_P0LIST);
- }
- /* fall through */
- case OP_REAL_EVAL:
- #endif
- if (is_symbol(sc->code)) { /* symbol */
- x=find_slot_in_env(sc,sc->envir,sc->code,1);
- if (x != sc->NIL) {
- s_return(sc,slot_value_in_env(x));
- } else {
- Error_1(sc,"eval: unbound variable:", sc->code);
- }
- } else if (is_pair(sc->code)) {
- if (is_syntax(x = car(sc->code))) { /* SYNTAX */
- sc->code = cdr(sc->code);
- s_goto(sc,syntaxnum(x));
- } else {/* first, eval top element and eval arguments */
- s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
- /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- }
- } else {
- s_return(sc,sc->code);
- }
- case OP_E0ARGS: /* eval arguments */
- if (is_macro(sc->value)) { /* macro expansion */
- s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
- sc->args = cons(sc,sc->code, sc->NIL);
- sc->code = sc->value;
- s_goto(sc,OP_APPLY);
- } else {
- sc->code = cdr(sc->code);
- s_goto(sc,OP_E1ARGS);
- }
- case OP_E1ARGS: /* eval arguments */
- sc->args = cons(sc, sc->value, sc->args);
- if (is_pair(sc->code)) { /* continue */
- s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
- sc->code = car(sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_EVAL);
- } else { /* end */
- sc->args = reverse_in_place(sc, sc->NIL, sc->args);
- sc->code = car(sc->args);
- sc->args = cdr(sc->args);
- s_goto(sc,OP_APPLY);
- }
- #if USE_TRACING
- case OP_TRACING: {
- int tr=sc->tracing;
- sc->tracing=ivalue(car(sc->args));
- s_return(sc,mk_integer(sc,tr));
- }
- #endif
- case OP_APPLY: /* apply 'code' to 'args' */
- #if USE_TRACING
- if(sc->tracing) {
- s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
- sc->print_flag = 1;
- /* sc->args=cons(sc,sc->code,sc->args);*/
- putstr(sc,"\nApply to: ");
- s_goto(sc,OP_P0LIST);
- }
- /* fall through */
- case OP_REAL_APPLY:
- #endif
- if (is_proc(sc->code)) {
- s_goto(sc,procnum(sc->code)); /* PROCEDURE */
- } else if (is_foreign(sc->code)) {
- x=sc->code->_object._ff(sc,sc->args);
- s_return(sc,x);
- } else if (is_closure(sc->code) || is_macro(sc->code)
- || is_promise(sc->code)) { /* CLOSURE */
- /* Should not accept promise */
- /* make environment */
- new_frame_in_env(sc, closure_env(sc->code));
- for (x = car(closure_code(sc->code)), y = sc->args;
- is_pair(x); x = cdr(x), y = cdr(y)) {
- if (y == sc->NIL) {
- Error_0(sc,"not enough arguments");
- } else {
- new_slot_in_env(sc, car(x), car(y));
- }
- }
- if (x == sc->NIL) {
- /*--
- * if (y != sc->NIL) {
- * Error_0(sc,"too many arguments");
- * }
- */
- } else if (is_symbol(x))
- new_slot_in_env(sc, x, y);
- else {
- Error_1(sc,"syntax error in closure: not a symbol:", x);
- }
- sc->code = cdr(closure_code(sc->code));
- sc->args = sc->NIL;
- s_goto(sc,OP_BEGIN);
- } else if (is_continuation(sc->code)) { /* CONTINUATION */
- sc->dump = cont_dump(sc->code);
- s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
- } else {
- Error_0(sc,"illegal function");
- }
- case OP_DOMACRO: /* do macro */
- sc->code = sc->value;
- s_goto(sc,OP_EVAL);
- case OP_LAMBDA: /* lambda */
- s_return(sc,mk_closure(sc, sc->code, sc->envir));
- case OP_MKCLOSURE: /* make-closure */
- x=car(sc->args);
- if(car(x)==sc->LAMBDA) {
- x=cdr(x);
- }
- if(cdr(sc->args)==sc->NIL) {
- y=sc->envir;
- } else {
- y=cadr(sc->args);
- }
- s_return(sc,mk_closure(sc, x, y));
- case OP_QUOTE: /* quote */
- x=car(sc->code);
- s_return(sc,car(sc->code));
- case OP_DEF0: /* define */
- if(is_immutable(car(sc->code)))
- Error_1(sc,"define: unable to alter immutable", car(sc->code));
- if (is_pair(car(sc->code))) {
- x = caar(sc->code);
- sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
- } else {
- x = car(sc->code);
- sc->code = cadr(sc->code);
- }
- if (!is_symbol(x)) {
- Error_0(sc,"variable is not a symbol");
- }
- s_save(sc,OP_DEF1, sc->NIL, x);
- s_goto(sc,OP_EVAL);
- case OP_DEF1: /* define */
- x=find_slot_in_env(sc,sc->envir,sc->code,0);
- if (x != sc->NIL) {
- set_slot_in_env(sc, x, sc->value);
- } else {
- new_slot_in_env(sc, sc->code, sc->value);
- }
- s_return(sc,sc->code);
- case OP_DEFP: /* defined? */
- x=sc->envir;
- if(cdr(sc->args)!=sc->NIL) {
- x=cadr(sc->args);
- }
- s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
- case OP_SET0: /* set! */
- if(is_immutable(car(sc->code)))
- Error_1(sc,"set!: unable to alter immutable variable",car(sc->code));
- s_save(sc,OP_SET1, sc->NIL, car(sc->code));
- sc->code = cadr(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_SET1: /* set! */
- y=find_slot_in_env(sc,sc->envir,sc->code,1);
- if (y != sc->NIL) {
- set_slot_in_env(sc, y, sc->value);
- s_return(sc,sc->value);
- } else {
- Error_1(sc,"set!: unbound variable:", sc->code);
- }
- case OP_BEGIN: /* begin */
- if (!is_pair(sc->code)) {
- s_return(sc,sc->code);
- }
- if (cdr(sc->code) != sc->NIL) {
- s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
- }
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_IF0: /* if */
- s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_IF1: /* if */
- if (is_true(sc->value))
- sc->code = car(sc->code);
- else
- sc->code = cadr(sc->code); /* (if #f 1) ==> () because
- * car(sc->NIL) = sc->NIL */
- s_goto(sc,OP_EVAL);
- case OP_LET0: /* let */
- sc->args = sc->NIL;
- sc->value = sc->code;
- sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
- s_goto(sc,OP_LET1);
- case OP_LET1: /* let (calculate parameters) */
- sc->args = cons(sc, sc->value, sc->args);
- if (is_pair(sc->code)) { /* continue */
- s_save(sc,OP_LET1, sc->args, cdr(sc->code));
- sc->code = cadar(sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_EVAL);
- } else { /* end */
- sc->args = reverse_in_place(sc, sc->NIL, sc->args);
- sc->code = car(sc->args);
- sc->args = cdr(sc->args);
- s_goto(sc,OP_LET2);
- }
- case OP_LET2: /* let */
- new_frame_in_env(sc, sc->envir);
- for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
- y != sc->NIL; x = cdr(x), y = cdr(y)) {
- new_slot_in_env(sc, caar(x), car(y));
- }
- if (is_symbol(car(sc->code))) { /* named let */
- for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
- sc->args = cons(sc, caar(x), sc->args);
- }
- x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
- new_slot_in_env(sc, car(sc->code), x);
- sc->code = cddr(sc->code);
- sc->args = sc->NIL;
- } else {
- sc->code = cdr(sc->code);
- sc->args = sc->NIL;
- }
- s_goto(sc,OP_BEGIN);
- case OP_LET0AST: /* let* */
- if (car(sc->code) == sc->NIL) {
- new_frame_in_env(sc, sc->envir);
- sc->code = cdr(sc->code);
- s_goto(sc,OP_BEGIN);
- }
- s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
- sc->code = cadaar(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_LET1AST: /* let* (make new frame) */
- new_frame_in_env(sc, sc->envir);
- s_goto(sc,OP_LET2AST);
- case OP_LET2AST: /* let* (calculate parameters) */
- new_slot_in_env(sc, caar(sc->code), sc->value);
- sc->code = cdr(sc->code);
- if (is_pair(sc->code)) { /* continue */
- s_save(sc,OP_LET2AST, sc->args, sc->code);
- sc->code = cadar(sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_EVAL);
- } else { /* end */
- sc->code = sc->args;
- sc->args = sc->NIL;
- s_goto(sc,OP_BEGIN);
- }
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T;
- }
- static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
- pointer x, y;
- switch (op) {
- case OP_LET0REC: /* letrec */
- new_frame_in_env(sc, sc->envir);
- sc->args = sc->NIL;
- sc->value = sc->code;
- sc->code = car(sc->code);
- s_goto(sc,OP_LET1REC);
- case OP_LET1REC: /* letrec (calculate parameters) */
- sc->args = cons(sc, sc->value, sc->args);
- if (is_pair(sc->code)) { /* continue */
- s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
- sc->code = cadar(sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_EVAL);
- } else { /* end */
- sc->args = reverse_in_place(sc, sc->NIL, sc->args);
- sc->code = car(sc->args);
- sc->args = cdr(sc->args);
- s_goto(sc,OP_LET2REC);
- }
- case OP_LET2REC: /* letrec */
- for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
- new_slot_in_env(sc, caar(x), car(y));
- }
- sc->code = cdr(sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_BEGIN);
- case OP_COND0: /* cond */
- if (!is_pair(sc->code)) {
- Error_0(sc,"syntax error in cond");
- }
- s_save(sc,OP_COND1, sc->NIL, sc->code);
- sc->code = caar(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_COND1: /* cond */
- if (is_true(sc->value)) {
- if ((sc->code = cdar(sc->code)) == sc->NIL) {
- s_return(sc,sc->value);
- }
- if(car(sc->code)==sc->FEED_TO) {
- if(!is_pair(cdr(sc->code))) {
- Error_0(sc,"syntax error in cond");
- }
- x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
- sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
- s_goto(sc,OP_EVAL);
- }
- s_goto(sc,OP_BEGIN);
- } else {
- if ((sc->code = cdr(sc->code)) == sc->NIL) {
- s_return(sc,sc->NIL);
- } else {
- s_save(sc,OP_COND1, sc->NIL, sc->code);
- sc->code = caar(sc->code);
- s_goto(sc,OP_EVAL);
- }
- }
- case OP_DELAY: /* delay */
- x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
- typeflag(x)=T_PROMISE;
- s_return(sc,x);
- case OP_AND0: /* and */
- if (sc->code == sc->NIL) {
- s_return(sc,sc->T);
- }
- s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_AND1: /* and */
- if (is_false(sc->value)) {
- s_return(sc,sc->value);
- } else if (sc->code == sc->NIL) {
- s_return(sc,sc->value);
- } else {
- s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- }
- case OP_OR0: /* or */
- if (sc->code == sc->NIL) {
- s_return(sc,sc->F);
- }
- s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_OR1: /* or */
- if (is_true(sc->value)) {
- s_return(sc,sc->value);
- } else if (sc->code == sc->NIL) {
- s_return(sc,sc->value);
- } else {
- s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- }
- case OP_C0STREAM: /* cons-stream */
- s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_C1STREAM: /* cons-stream */
- sc->args = sc->value; /* save sc->value to register sc->args for gc */
- x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
- typeflag(x)=T_PROMISE;
- s_return(sc,cons(sc, sc->args, x));
- case OP_MACRO0: /* macro */
- if (is_pair(car(sc->code))) {
- x = caar(sc->code);
- sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
- } else {
- x = car(sc->code);
- sc->code = cadr(sc->code);
- }
- if (!is_symbol(x)) {
- Error_0(sc,"variable is not a symbol");
- }
- s_save(sc,OP_MACRO1, sc->NIL, x);
- s_goto(sc,OP_EVAL);
- case OP_MACRO1: /* macro */
- typeflag(sc->value) = T_MACRO;
- x = find_slot_in_env(sc, sc->envir, sc->code, 0);
- if (x != sc->NIL) {
- set_slot_in_env(sc, x, sc->value);
- } else {
- new_slot_in_env(sc, sc->code, sc->value);
- }
- s_return(sc,sc->code);
- case OP_CASE0: /* case */
- s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
- sc->code = car(sc->code);
- s_goto(sc,OP_EVAL);
- case OP_CASE1: /* case */
- for (x = sc->code; x != sc->NIL; x = cdr(x)) {
- if (!is_pair(y = caar(x))) {
- break;
- }
- for ( ; y != sc->NIL; y = cdr(y)) {
- if (eqv(car(y), sc->value)) {
- break;
- }
- }
- if (y != sc->NIL) {
- break;
- }
- }
- if (x != sc->NIL) {
- if (is_pair(caar(x))) {
- sc->code = cdar(x);
- s_goto(sc,OP_BEGIN);
- } else {/* else */
- s_save(sc,OP_CASE2, sc->NIL, cdar(x));
- sc->code = caar(x);
- s_goto(sc,OP_EVAL);
- }
- } else {
- s_return(sc,sc->NIL);
- }
- case OP_CASE2: /* case */
- if (is_true(sc->value)) {
- s_goto(sc,OP_BEGIN);
- } else {
- s_return(sc,sc->NIL);
- }
- case OP_PAPPLY: /* apply */
- sc->code = car(sc->args);
- sc->args = list_star(sc,cdr(sc->args));
- /*sc->args = cadr(sc->args);*/
- s_goto(sc,OP_APPLY);
- case OP_PEVAL: /* eval */
- if(cdr(sc->args)!=sc->NIL) {
- sc->envir=cadr(sc->args);
- }
- sc->code = car(sc->args);
- s_goto(sc,OP_EVAL);
- case OP_CONTINUATION: /* call-with-current-continuation */
- sc->code = car(sc->args);
- sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
- s_goto(sc,OP_APPLY);
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T;
- }
- static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
- pointer x;
- num v;
- #if USE_MATH
- double dd;
- #endif
- switch (op) {
- #if USE_MATH
- case OP_INEX2EX: /* inexact->exact */
- x=car(sc->args);
- if(is_integer(x)) {
- s_return(sc,x);
- } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
- s_return(sc,mk_integer(sc,ivalue(x)));
- } else {
- Error_1(sc,"inexact->exact: not integral:",x);
- }
- case OP_EXP:
- x=car(sc->args);
- s_return(sc, mk_real(sc, exp(rvalue(x))));
- case OP_LOG:
- x=car(sc->args);
- s_return(sc, mk_real(sc, log(rvalue(x))));
- case OP_SIN:
- x=car(sc->args);
- s_return(sc, mk_real(sc, sin(rvalue(x))));
- case OP_COS:
- x=car(sc->args);
- s_return(sc, mk_real(sc, cos(rvalue(x))));
- case OP_TAN:
- x=car(sc->args);
- s_return(sc, mk_real(sc, tan(rvalue(x))));
- case OP_ASIN:
- x=car(sc->args);
- s_return(sc, mk_real(sc, asin(rvalue(x))));
- case OP_ACOS:
- x=car(sc->args);
- s_return(sc, mk_real(sc, acos(rvalue(x))));
- case OP_ATAN:
- x=car(sc->args);
- if(cdr(sc->args)==sc->NIL) {
- s_return(sc, mk_real(sc, atan(rvalue(x))));
- } else {
- pointer y=cadr(sc->args);
- s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
- }
- case OP_SQRT:
- x=car(sc->args);
- s_return(sc, mk_real(sc, sqrt(rvalue(x))));
- case OP_EXPT:
- x=car(sc->args);
- if(cdr(sc->args)==sc->NIL) {
- Error_0(sc,"expt: needs two arguments");
- } else {
- pointer y=cadr(sc->args);
- s_return(sc, mk_real(sc, pow(rvalue(x),rvalue(y))));
- }
- case OP_FLOOR:
- x=car(sc->args);
- s_return(sc, mk_real(sc, floor(rvalue(x))));
- case OP_CEILING:
- x=car(sc->args);
- s_return(sc, mk_real(sc, ceil(rvalue(x))));
- case OP_TRUNCATE : {
- double rvalue_of_x ;
- x=car(sc->args);
- rvalue_of_x = rvalue(x) ;
- if (rvalue_of_x > 0) {
- s_return(sc, mk_real(sc, floor(rvalue_of_x)));
- } else {
- s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
- }
- }
- case OP_ROUND:
- x=car(sc->args);
- s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
- #endif
- case OP_ADD: /* + */
- v=num_zero;
- for (x = sc->args; x != sc->NIL; x = cdr(x)) {
- v=num_add(v,nvalue(car(x)));
- }
- s_return(sc,mk_number(sc, v));
- case OP_MUL: /* * */
- v=num_one;
- for (x = sc->args; x != sc->NIL; x = cdr(x)) {
- v=num_mul(v,nvalue(car(x)));
- }
- s_return(sc,mk_number(sc, v));
- case OP_SUB: /* - */
- if(cdr(sc->args)==sc->NIL) {
- x=sc->args;
- v=num_zero;
- } else {
- x = cdr(sc->args);
- v = nvalue(car(sc->args));
- }
- for (; x != sc->NIL; x = cdr(x)) {
- v=num_sub(v,nvalue(car(x)));
- }
- s_return(sc,mk_number(sc, v));
- case OP_DIV: /* / */
- if(cdr(sc->args)==sc->NIL) {
- x=sc->args;
- v=num_one;
- } else {
- x = cdr(sc->args);
- v = nvalue(car(sc->args));
- }
- for (; x != sc->NIL; x = cdr(x)) {
- if (!is_zero_double(rvalue(car(x))))
- v=num_div(v,nvalue(car(x)));
- else {
- Error_0(sc,"/: division by zero");
- }
- }
- s_return(sc,mk_number(sc, v));
- case OP_INTDIV: /* quotient */
- if(cdr(sc->args)==sc->NIL) {
- x=sc->args;
- v=num_one;
- } else {
- x = cdr(sc->args);
- v = nvalue(car(sc->args));
- }
- for (; x != sc->NIL; x = cdr(x)) {
- if (ivalue(car(x)) != 0)
- v=num_intdiv(v,nvalue(car(x)));
- else {
- Error_0(sc,"quotient: division by zero");
- }
- }
- s_return(sc,mk_number(sc, v));
- case OP_REM: /* remainder */
- v = nvalue(car(sc->args));
- if (ivalue(cadr(sc->args)) != 0)
- v=num_rem(v,nvalue(cadr(sc->args)));
- else {
- Error_0(sc,"remainder: division by zero");
- }
- s_return(sc,mk_number(sc, v));
- case OP_MOD: /* modulo */
- v = nvalue(car(sc->args));
- if (ivalue(cadr(sc->args)) != 0)
- v=num_mod(v,nvalue(cadr(sc->args)));
- else {
- Error_0(sc,"modulo: division by zero");
- }
- s_return(sc,mk_number(sc, v));
- case OP_CAR: /* car */
- s_return(sc,caar(sc->args));
- case OP_CDR: /* cdr */
- s_return(sc,cdar(sc->args));
- case OP_CONS: /* cons */
- cdr(sc->args) = cadr(sc->args);
- s_return(sc,sc->args);
- case OP_SETCAR: /* set-car! */
- if(!is_immutable(car(sc->args))) {
- caar(sc->args) = cadr(sc->args);
- s_return(sc,car(sc->args));
- } else {
- Error_0(sc,"set-car!: unable to alter immutable pair");
- }
- case OP_SETCDR: /* set-cdr! */
- if(!is_immutable(car(sc->args))) {
- cdar(sc->args) = cadr(sc->args);
- s_return(sc,car(sc->args));
- } else {
- Error_0(sc,"set-cdr!: unable to alter immutable pair");
- }
- case OP_CHAR2INT: { /* char->integer */
- char c;
- c=(char)ivalue(car(sc->args));
- s_return(sc,mk_integer(sc,(unsigned char)c));
- }
- case OP_INT2CHAR: { /* integer->char */
- unsigned char c;
- c=(unsigned char)ivalue(car(sc->args));
- s_return(sc,mk_character(sc,(char)c));
- }
- case OP_CHARUPCASE: {
- unsigned char c;
- c=(unsigned char)ivalue(car(sc->args));
- c=toupper(c);
- s_return(sc,mk_character(sc,(char)c));
- }
- case OP_CHARDNCASE: {
- unsigned char c;
- c=(unsigned char)ivalue(car(sc->args));
- c=tolower(c);
- s_return(sc,mk_character(sc,(char)c));
- }
- case OP_STR2SYM: /* string->symbol */
- s_return(sc,mk_symbol(sc,strvalue(car(sc->args))));
- case OP_STR2ATOM: /* string->atom */ {
- char *s=strvalue(car(sc->args));
- if(*s=='#') {
- s_return(sc, mk_sharp_const(sc, s+1));
- } else {
- s_return(sc, mk_atom(sc, s));
- }
- }
- case OP_SYM2STR: /* symbol->string */
- x=mk_string(sc,symname(car(sc->args)));
- setimmutable(x);
- s_return(sc,x);
- case OP_ATOM2STR: /* atom->string */
- x=car(sc->args);
- if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
- char *p;
- int len;
- atom2str(sc,x,0,&p,&len);
- s_return(sc,mk_counted_string(sc,p,len));
- } else {
- Error_1(sc, "atom->string: not an atom:", x);
- }
- case OP_MKSTRING: { /* make-string */
- int fill=' ';
- int len;
- len=ivalue(car(sc->args));
- if(cdr(sc->args)!=sc->NIL) {
- fill=charvalue(cadr(sc->args));
- }
- s_return(sc,mk_empty_string(sc,len,(char)fill));
- }
- case OP_STRLEN: /* string-length */
- s_return(sc,mk_integer(sc,strlength(car(sc->args))));
- case OP_STRREF: { /* string-ref */
- char *str;
- int index;
- str=strvalue(car(sc->args));
- index=ivalue(cadr(sc->args));
- if(index>=strlength(car(sc->args))) {
- Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
- }
- s_return(sc,mk_character(sc,((unsigned char*)str)[index]));
- }
- case OP_STRSET: { /* string-set! */
- char *str;
- int index;
- int c;
- if(is_immutable(car(sc->args))) {
- Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args));
- }
- str=strvalue(car(sc->args));
- index=ivalue(cadr(sc->args));
- if(index>=strlength(car(sc->args))) {
- Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
- }
- c=charvalue(caddr(sc->args));
- str[index]=(char)c;
- s_return(sc,car(sc->args));
- }
- case OP_STRAPPEND: { /* string-append */
- /* in 1.29 string-append was in Scheme in init.scm but was too slow */
- int len = 0;
- pointer newstr;
- char *pos;
- /* compute needed length for new string */
- for (x = sc->args; x != sc->NIL; x = cdr(x)) {
- len += strlength(car(x));
- }
- newstr = mk_empty_string(sc, len, ' ');
- /* store the contents of the argument strings into the new string */
- for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
- pos += strlength(car(x)), x = cdr(x)) {
- memcpy(pos, strvalue(car(x)), strlength(car(x)));
- }
- s_return(sc, newstr);
- }
- case OP_SUBSTR: { /* substring */
- char *str;
- int index0;
- int index1;
- int len;
- str=strvalue(car(sc->args));
- index0=ivalue(cadr(sc->args));
- if(index0>strlength(car(sc->args))) {
- Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
- }
- if(cddr(sc->args)!=sc->NIL) {
- index1=ivalue(caddr(sc->args));
- if(index1>strlength(car(sc->args)) || index1<index0) {
- Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
- }
- } else {
- index1=strlength(car(sc->args));
- }
- len=index1-index0;
- x=mk_empty_string(sc,len,' ');
- memcpy(strvalue(x),str+index0,len);
- strvalue(x)[len]=0;
- s_return(sc,x);
- }
- case OP_VECTOR: { /* vector */
- int i;
- pointer vec;
- int len=list_length(sc,sc->args);
- if(len<0) {
- Error_1(sc,"vector: not a proper list:",sc->args);
- }
- vec=mk_vector(sc,len);
- for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
- set_vector_elem(vec,i,car(x));
- }
- s_return(sc,vec);
- }
- case OP_MKVECTOR: { /* make-vector */
- pointer fill=sc->NIL;
- int len;
- pointer vec;
- len=ivalue(car(sc->args));
- if(cdr(sc->args)!=sc->NIL) {
- fill=cadr(sc->args);
- }
- vec=mk_vector(sc,len);
- if(fill!=sc->NIL) {
- fill_vector(vec,fill);
- }
- s_return(sc,vec);
- }
- case OP_VECLEN: /* vector-length */
- s_return(sc,mk_integer(sc,ivalue(car(sc->args))));
- case OP_VECREF: { /* vector-ref */
- int index;
- index=ivalue(cadr(sc->args));
- if(index>=ivalue(car(sc->args))) {
- Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
- }
- s_return(sc,vector_elem(car(sc->args),index));
- }
- case OP_VECSET: { /* vector-set! */
- int index;
- if(is_immutable(car(sc->args))) {
- Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
- }
- index=ivalue(cadr(sc->args));
- if(index>=ivalue(car(sc->args))) {
- Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
- }
- set_vector_elem(car(sc->args),index,caddr(sc->args));
- s_return(sc,car(sc->args));
- }
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T;
- }
- static int list_length(scheme *sc, pointer a) {
- int v=0;
- pointer x;
- for (x = a, v = 0; is_pair(x); x = cdr(x)) {
- ++v;
- }
- if(x==sc->NIL) {
- return v;
- }
- return -1;
- }
- static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
- pointer x;
- num v;
- int (*comp_func)(num,num)=0;
- switch (op) {
- case OP_NOT: /* not */
- s_retbool(is_false(car(sc->args)));
- case OP_BOOLP: /* boolean? */
- s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
- case OP_EOFOBJP: /* boolean? */
- s_retbool(car(sc->args) == sc->EOF_OBJ);
- case OP_NULLP: /* null? */
- s_retbool(car(sc->args) == sc->NIL);
- case OP_NUMEQ: /* = */
- case OP_LESS: /* < */
- case OP_GRE: /* > */
- case OP_LEQ: /* <= */
- case OP_GEQ: /* >= */
- switch(op) {
- case OP_NUMEQ: comp_func=num_eq; break;
- case OP_LESS: comp_func=num_lt; break;
- case OP_GRE: comp_func=num_gt; break;
- case OP_LEQ: comp_func=num_le; break;
- case OP_GEQ: comp_func=num_ge; break;
- }
- x=sc->args;
- v=nvalue(car(x));
- x=cdr(x);
- for (; x != sc->NIL; x = cdr(x)) {
- if(!comp_func(v,nvalue(car(x)))) {
- s_retbool(0);
- }
- v=nvalue(car(x));
- }
- s_retbool(1);
- case OP_SYMBOLP: /* symbol? */
- s_retbool(is_symbol(car(sc->args)));
- case OP_NUMBERP: /* number? */
- s_retbool(is_number(car(sc->args)));
- case OP_STRINGP: /* string? */
- s_retbool(is_string(car(sc->args)));
- case OP_INTEGERP: /* integer? */
- s_retbool(is_integer(car(sc->args)));
- case OP_REALP: /* real? */
- s_retbool(is_number(car(sc->args))); /* All numbers are real */
- case OP_CHARP: /* char? */
- s_retbool(is_character(car(sc->args)));
- #if USE_CHAR_CLASSIFIERS
- case OP_CHARAP: /* char-alphabetic? */
- s_retbool(Cisalpha(ivalue(car(sc->args))));
- case OP_CHARNP: /* char-numeric? */
- s_retbool(Cisdigit(ivalue(car(sc->args))));
- case OP_CHARWP: /* char-whitespace? */
- s_retbool(Cisspace(ivalue(car(sc->args))));
- case OP_CHARUP: /* char-upper-case? */
- s_retbool(Cisupper(ivalue(car(sc->args))));
- case OP_CHARLP: /* char-lower-case? */
- s_retbool(Cislower(ivalue(car(sc->args))));
- #endif
- case OP_PORTP: /* port? */
- s_retbool(is_port(car(sc->args)));
- case OP_INPORTP: /* input-port? */
- s_retbool(is_inport(car(sc->args)));
- case OP_OUTPORTP: /* output-port? */
- s_retbool(is_outport(car(sc->args)));
- case OP_PROCP: /* procedure? */
- /*--
- * continuation should be procedure by the example
- * (call-with-current-continuation procedure?) ==> #t
- * in R^3 report sec. 6.9
- */
- s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
- || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
- case OP_PAIRP: /* pair? */
- s_retbool(is_pair(car(sc->args)));
- case OP_LISTP: { /* list? */
- pointer slow, fast;
- slow = fast = car(sc->args);
- while (1) {
- if (!is_pair(fast)) s_retbool(fast == sc->NIL);
- fast = cdr(fast);
- if (!is_pair(fast)) s_retbool(fast == sc->NIL);
- fast = cdr(fast);
- slow = cdr(slow);
- if (fast == slow) {
- /* the fast pointer has looped back around and caught up
- with the slow pointer, hence the structure is circular,
- not of finite length, and therefore not a list */
- s_retbool(0);
- }
- }
- }
- case OP_ENVP: /* environment? */
- s_retbool(is_environment(car(sc->args)));
- case OP_VECTORP: /* vector? */
- s_retbool(is_vector(car(sc->args)));
- case OP_EQ: /* eq? */
- s_retbool(car(sc->args) == cadr(sc->args));
- case OP_EQV: /* eqv? */
- s_retbool(eqv(car(sc->args), cadr(sc->args)));
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T;
- }
- static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
- pointer x, y;
- switch (op) {
- case OP_FORCE: /* force */
- sc->code = car(sc->args);
- if (is_promise(sc->code)) {
- /* Should change type to closure here */
- s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
- sc->args = sc->NIL;
- s_goto(sc,OP_APPLY);
- } else {
- s_return(sc,sc->code);
- }
- case OP_SAVE_FORCED: /* Save forced value replacing promise */
- memcpy(sc->code,sc->value,sizeof(struct cell));
- s_return(sc,sc->value);
- case OP_WRITE: /* write */
- case OP_DISPLAY: /* display */
- case OP_WRITE_CHAR: /* write-char */
- if(is_pair(cdr(sc->args))) {
- if(cadr(sc->args)!=sc->outport) {
- x=cons(sc,sc->outport,sc->NIL);
- s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
- sc->outport=cadr(sc->args);
- }
- }
- sc->args = car(sc->args);
- if(op==OP_WRITE) {
- sc->print_flag = 1;
- } else {
- sc->print_flag = 0;
- }
- s_goto(sc,OP_P0LIST);
- case OP_NEWLINE: /* newline */
- if(is_pair(sc->args)) {
- if(car(sc->args)!=sc->outport) {
- x=cons(sc,sc->outport,sc->NIL);
- s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
- sc->outport=car(sc->args);
- }
- }
- putstr(sc, "\n");
- s_return(sc,sc->T);
- case OP_ERR0: /* error */
- sc->retcode=-1;
- if (!is_string(car(sc->args))) {
- sc->args=cons(sc,mk_string(sc," -- "),sc->args);
- setimmutable(car(sc->args));
- }
- putstr(sc, "Error: ");
- putstr(sc, strvalue(car(sc->args)));
- sc->args = cdr(sc->args);
- s_goto(sc,OP_ERR1);
- case OP_ERR1: /* error */
- putstr(sc, " ");
- if (sc->args != sc->NIL) {
- s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
- sc->args = car(sc->args);
- sc->print_flag = 1;
- s_goto(sc,OP_P0LIST);
- } else {
- putstr(sc, "\n");
- if(sc->interactive_repl) {
- s_goto(sc,OP_T0LVL);
- } else {
- return sc->NIL;
- }
- }
- case OP_REVERSE: /* reverse */
- s_return(sc,reverse(sc, car(sc->args)));
- case OP_LIST_STAR: /* list* */
- s_return(sc,list_star(sc,sc->args));
- case OP_APPEND: /* append */
- if(sc->args==sc->NIL) {
- s_return(sc,sc->NIL);
- }
- x=car(sc->args);
- if(cdr(sc->args)==sc->NIL) {
- s_return(sc,sc->args);
- }
- for (y = cdr(sc->args); y != sc->NIL; y = cdr(y)) {
- x=append(sc,x,car(y));
- }
- s_return(sc,x);
- #if USE_PLIST
- case OP_PUT: /* put */
- if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
- Error_0(sc,"illegal use of put");
- }
- for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
- if (caar(x) == y) {
- break;
- }
- }
- if (x != sc->NIL)
- cdar(x) = caddr(sc->args);
- else
- symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)),
- symprop(car(sc->args)));
- s_return(sc,sc->T);
- case OP_GET: /* get */
- if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
- Error_0(sc,"illegal use of get");
- }
- for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
- if (caar(x) == y) {
- break;
- }
- }
- if (x != sc->NIL) {
- s_return(sc,cdar(x));
- } else {
- s_return(sc,sc->NIL);
- }
- #endif /* USE_PLIST */
- case OP_QUIT: /* quit */
- if(is_pair(sc->args)) {
- sc->retcode=ivalue(car(sc->args));
- }
- return (sc->NIL);
- case OP_GC: /* gc */
- gc(sc, sc->NIL, sc->NIL);
- s_return(sc,sc->T);
- case OP_GCVERB: /* gc-verbose */
- { int was = sc->gc_verbose;
-
- sc->gc_verbose = (car(sc->args) != sc->F);
- s_retbool(was);
- }
- case OP_NEWSEGMENT: /* new-segment */
- if (!is_pair(sc->args) || !is_number(car(sc->args))) {
- Error_0(sc,"new-segment: argument must be a number");
- }
- alloc_cellseg(sc, (int) ivalue(car(sc->args)));
- s_return(sc,sc->T);
- case OP_OBLIST: /* oblist */
- s_return(sc, oblist_all_symbols(sc));
- case OP_CURR_INPORT: /* current-input-port */
- s_return(sc,sc->inport);
- case OP_CURR_OUTPORT: /* current-output-port */
- s_return(sc,sc->outport);
- case OP_OPEN_INFILE: /* open-input-file */
- case OP_OPEN_OUTFILE: /* open-output-file */
- case OP_OPEN_INOUTFILE: /* open-input-output-file */ {
- int prop=0;
- pointer p;
- switch(op) {
- case OP_OPEN_INFILE: prop=port_input; break;
- case OP_OPEN_OUTFILE: prop=port_output; break;
- case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
- }
- p=port_from_filename(sc,strvalue(car(sc->args)),prop);
- if(p==sc->NIL) {
- s_return(sc,sc->F);
- }
- s_return(sc,p);
- }
-
- #if USE_STRING_PORTS
- case OP_OPEN_INSTRING: /* open-input-string */
- case OP_OPEN_OUTSTRING: /* open-output-string */
- case OP_OPEN_INOUTSTRING: /* open-input-output-string */ {
- int prop=0;
- pointer p;
- switch(op) {
- case OP_OPEN_INSTRING: prop=port_input; break;
- case OP_OPEN_OUTSTRING: prop=port_output; break;
- case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break;
- }
- p=port_from_string(sc, strvalue(car(sc->args)),
- strvalue(car(sc->args))+strlength(car(sc->args)), prop);
- if(p==sc->NIL) {
- s_return(sc,sc->F);
- }
- s_return(sc,p);
- }
- #endif
- case OP_CLOSE_INPORT: /* close-input-port */
- port_close(sc,car(sc->args),port_input);
- s_return(sc,sc->T);
- case OP_CLOSE_OUTPORT: /* close-output-port */
- port_close(sc,car(sc->args),port_output);
- s_return(sc,sc->T);
- case OP_INT_ENV: /* interaction-environment */
- s_return(sc,sc->global_env);
- case OP_CURR_ENV: /* current-environment */
- s_return(sc,sc->envir);
- }
- return sc->T;
- }
- static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
- pointer x;
- if(sc->nesting!=0) {
- int n=sc->nesting;
- sc->nesting=0;
- sc->retcode=-1;
- Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
- }
- switch (op) {
- /* ========== reading part ========== */
- case OP_READ:
- if(!is_pair(sc->args)) {
- s_goto(sc,OP_READ_INTERNAL);
- }
- if(!is_inport(car(sc->args))) {
- Error_1(sc,"read: not an input port:",car(sc->args));
- }
- if(car(sc->args)==sc->inport) {
- s_goto(sc,OP_READ_INTERNAL);
- }
- x=sc->inport;
- sc->inport=car(sc->args);
- x=cons(sc,x,sc->NIL);
- s_save(sc,OP_SET_INPORT, x, sc->NIL);
- s_goto(sc,OP_READ_INTERNAL);
- case OP_READ_CHAR: /* read-char */
- case OP_PEEK_CHAR: /* peek-char */ {
- int c;
- if(is_pair(sc->args)) {
- if(car(sc->args)!=sc->inport) {
- x=sc->inport;
- x=cons(sc,x,sc->NIL);
- s_save(sc,OP_SET_INPORT, x, sc->NIL);
- sc->inport=car(sc->args);
- }
- }
- c=inchar(sc);
- if(c==EOF) {
- s_return(sc,sc->EOF_OBJ);
- }
- if(sc->op==OP_PEEK_CHAR) {
- backchar(sc,c);
- }
- s_return(sc,mk_character(sc,c));
- }
- case OP_CHAR_READY: /* char-ready? */ {
- pointer p=sc->inport;
- int res;
- if(is_pair(sc->args)) {
- p=car(sc->args);
- }
- res=p->_object._port->kind&port_string;
- s_retbool(res);
- }
- case OP_SET_INPORT: /* set-input-port */
- sc->inport=car(sc->args);
- s_return(sc,sc->value);
- case OP_SET_OUTPORT: /* set-output-port */
- sc->outport=car(sc->args);
- s_return(sc,sc->value);
- case OP_RDSEXPR:
- switch (sc->tok) {
- case TOK_EOF:
- if(sc->inport==sc->loadport) {
- sc->args=sc->NIL;
- s_goto(sc,OP_QUIT);
- } else {
- s_return(sc,sc->EOF_OBJ);
- }
- /*
- * Commented out because we now skip comments in the scanner
- *
- case TOK_COMMENT: {
- int c;
- while ((c=inchar(sc)) != '\n' && c!=EOF)
- ;
- sc->tok = token(sc);
- s_goto(sc,OP_RDSEXPR);
- }
- */
- case TOK_VEC:
- s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
- /* fall through */
- case TOK_LPAREN:
- sc->tok = token(sc);
- if (sc->tok == TOK_RPAREN) {
- s_return(sc,sc->NIL);
- } else if (sc->tok == TOK_DOT) {
- Error_0(sc,"syntax error: illegal dot expression");
- } else {
- sc->nesting_stack[sc->file_i]++;
- s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
- s_goto(sc,OP_RDSEXPR);
- }
- case TOK_QUOTE:
- s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
- sc->tok = token(sc);
- s_goto(sc,OP_RDSEXPR);
- case TOK_BQUOTE:
- sc->tok = token(sc);
- if(sc->tok==TOK_VEC) {
- s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
- sc->tok=TOK_LPAREN;
- s_goto(sc,OP_RDSEXPR);
- } else {
- s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
- }
- s_goto(sc,OP_RDSEXPR);
- case TOK_COMMA:
- s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
- sc->tok = token(sc);
- s_goto(sc,OP_RDSEXPR);
- case TOK_ATMARK:
- s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
- sc->tok = token(sc);
- s_goto(sc,OP_RDSEXPR);
- case TOK_ATOM:
- s_return(sc,mk_atom(sc, readstr_upto(sc, "();\t\n\r ")));
- case TOK_DQUOTE:
- x=readstrexp(sc);
- if(x==sc->F) {
- Error_0(sc,"Error reading string");
- }
- setimmutable(x);
- s_return(sc,x);
- case TOK_SHARP: {
- pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
- if(f==sc->NIL) {
- Error_0(sc,"undefined sharp expression");
- } else {
- sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
- s_goto(sc,OP_EVAL);
- }
- }
- case TOK_SHARP_CONST:
- if ((x = mk_sharp_const(sc, readstr_upto(sc, "();\t\n\r "))) == sc->NIL) {
- Error_0(sc,"undefined sharp expression");
- } else {
- s_return(sc,x);
- }
- default:
- Error_0(sc,"syntax error: illegal token");
- }
- break;
- case OP_RDLIST: {
- sc->args = cons(sc, sc->value, sc->args);
- sc->tok = token(sc);
- /* We now skip comments in the scanner
- while (sc->tok == TOK_COMMENT) {
- int c;
- while ((c=inchar(sc)) != '\n' && c!=EOF)
- ;
- sc->tok = token(sc);
- }
- */
- if (sc->tok == TOK_RPAREN) {
- int c = inchar(sc);
- if (c != '\n') backchar(sc,c);
- sc->nesting_stack[sc->file_i]--;
- s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
- } else if (sc->tok == TOK_DOT) {
- s_save(sc,OP_RDDOT, sc->args, sc->NIL);
- sc->tok = token(sc);
- s_goto(sc,OP_RDSEXPR);
- } else {
- s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
- s_goto(sc,OP_RDSEXPR);
- }
- }
- case OP_RDDOT:
- if (token(sc) != TOK_RPAREN) {
- Error_0(sc,"syntax error: illegal dot expression");
- } else {
- sc->nesting_stack[sc->file_i]--;
- s_return(sc,reverse_in_place(sc, sc->value, sc->args));
- }
- case OP_RDQUOTE:
- s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)));
- case OP_RDQQUOTE:
- s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL)));
- case OP_RDQQUOTEVEC:
- s_return(sc,cons(sc, mk_symbol(sc,"apply"),
- cons(sc, mk_symbol(sc,"vector"),
- cons(sc,cons(sc, sc->QQUOTE,
- cons(sc,sc->value,sc->NIL)),
- sc->NIL))));
- case OP_RDUNQUOTE:
- s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL)));
- case OP_RDUQTSP:
- s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL)));
- case OP_RDVEC:
- /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
- s_goto(sc,OP_EVAL); Cannot be quoted*/
- /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
- s_return(sc,x); Cannot be part of pairs*/
- /*sc->code=mk_proc(sc,OP_VECTOR);
- sc->args=sc->value;
- s_goto(sc,OP_APPLY);*/
- sc->args=sc->value;
- s_goto(sc,OP_VECTOR);
- /* ========== printing part ========== */
- case OP_P0LIST:
- if(is_vector(sc->args)) {
- putstr(sc,"#(");
- sc->args=cons(sc,sc->args,mk_integer(sc,0));
- s_goto(sc,OP_PVECFROM);
- } else if(is_environment(sc->args)) {
- putstr(sc,"#<ENVIRONMENT>");
- s_return(sc,sc->T);
- } else if (!is_pair(sc->args)) {
- printatom(sc, sc->args, sc->print_flag);
- s_return(sc,sc->T);
- } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
- putstr(sc, "'");
- sc->args = cadr(sc->args);
- s_goto(sc,OP_P0LIST);
- } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
- putstr(sc, "`");
- sc->args = cadr(sc->args);
- s_goto(sc,OP_P0LIST);
- } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
- putstr(sc, ",");
- sc->args = cadr(sc->args);
- s_goto(sc,OP_P0LIST);
- } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
- putstr(sc, ",@");
- sc->args = cadr(sc->args);
- s_goto(sc,OP_P0LIST);
- } else {
- putstr(sc, "(");
- s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
- sc->args = car(sc->args);
- s_goto(sc,OP_P0LIST);
- }
- case OP_P1LIST:
- if (is_pair(sc->args)) {
- s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
- putstr(sc, " ");
- sc->args = car(sc->args);
- s_goto(sc,OP_P0LIST);
- } else if(is_vector(sc->args)) {
- s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
- putstr(sc, " . ");
- s_goto(sc,OP_P0LIST);
- } else {
- if (sc->args != sc->NIL) {
- putstr(sc, " . ");
- printatom(sc, sc->args, sc->print_flag);
- }
- putstr(sc, ")");
- s_return(sc,sc->T);
- }
- case OP_PVECFROM: {
- int i=ivalue_unchecked(cdr(sc->args));
- pointer vec=car(sc->args);
- int len=ivalue_unchecked(vec);
- if(i==len) {
- putstr(sc,")");
- s_return(sc,sc->T);
- } else {
- pointer elem=vector_elem(vec,i);
- ivalue_unchecked(cdr(sc->args))=i+1;
- s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
- sc->args=elem;
- putstr(sc," ");
- s_goto(sc,OP_P0LIST);
- }
- }
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T;
- }
- static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
- pointer x, y;
- long v;
- switch (op) {
- case OP_LIST_LENGTH: /* length */ /* a.k */
- v=list_length(sc,car(sc->args));
- if(v<0) {
- Error_1(sc,"length: not a list:",car(sc->args));
- }
- s_return(sc,mk_integer(sc, v));
- case OP_ASSQ: /* assq */ /* a.k */
- x = car(sc->args);
- for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
- if (!is_pair(car(y))) {
- Error_0(sc,"unable to handle non pair element");
- }
- if (x == caar(y))
- break;
- }
- if (is_pair(y)) {
- s_return(sc,car(y));
- } else {
- s_return(sc,sc->F);
- }
-
-
- case OP_GET_CLOSURE: /* get-closure-code */ /* a.k */
- sc->args = car(sc->args);
- if (sc->args == sc->NIL) {
- s_return(sc,sc->F);
- } else if (is_closure(sc->args)) {
- s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
- } else if (is_macro(sc->args)) {
- s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
- } else {
- s_return(sc,sc->F);
- }
- case OP_CLOSUREP: /* closure? */
- /*
- * Note, macro object is also a closure.
- * Therefore, (closure? <#MACRO>) ==> #t
- */
- s_retbool(is_closure(car(sc->args)));
- case OP_MACROP: /* macro? */
- s_retbool(is_macro(car(sc->args)));
- default:
- sprintf(sc->strbuff, "%d: illegal operator", sc->op);
- Error_0(sc,sc->strbuff);
- }
- return sc->T; /* NOTREACHED */
- }
- typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
- typedef int (*test_predicate)(pointer);
- static int is_any(pointer p) { return 1;}
- static int is_num_integer(pointer p) {
- return is_number(p) && ((p)->_object._number.is_fixnum);
- }
- static int is_nonneg(pointer p) {
- return is_num_integer(p) && ivalue(p)>=0;
- }
- /* Correspond carefully with following defines! */
- static struct {
- test_predicate fct;
- const char *kind;
- } tests[]={
- {0,0}, /* unused */
- {is_any, 0},
- {is_string, "string"},
- {is_symbol, "symbol"},
- {is_port, "port"},
- {0,"input port"},
- {0,"output_port"},
- {is_environment, "environment"},
- {is_pair, "pair"},
- {0, "pair or '()"},
- {is_character, "character"},
- {is_vector, "vector"},
- {is_number, "number"},
- {is_num_integer, "integer"},
- {is_nonneg, "non-negative integer"}
- };
- #define TST_NONE 0
- #define TST_ANY "\001"
- #define TST_STRING "\002"
- #define TST_SYMBOL "\003"
- #define TST_PORT "\004"
- #define TST_INPORT "\005"
- #define TST_OUTPORT "\006"
- #define TST_ENVIRONMENT "\007"
- #define TST_PAIR "\010"
- #define TST_LIST "\011"
- #define TST_CHAR "\012"
- #define TST_VECTOR "\013"
- #define TST_NUMBER "\014"
- #define TST_INTEGER "\015"
- #define TST_NATURAL "\016"
- typedef struct {
- dispatch_func func;
- char *name;
- int min_arity;
- int max_arity;
- char *arg_tests_encoding;
- } op_code_info;
- #define INF_ARG 0xffff
- static op_code_info dispatch_table[]= {
- #define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
- #include "opdefines.h"
- { 0 }
- };
- static const char *procname(pointer x) {
- int n=procnum(x);
- const char *name=dispatch_table[n].name;
- if(name==0) {
- name="ILLEGAL!";
- }
- return name;
- }
- /* kernel of this interpreter */
- static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
- int count=0;
- int old_op;
-
- sc->op = op;
- for (;;) {
- op_code_info *pcd=dispatch_table+sc->op;
- if (pcd->name!=0) { /* if built-in function, check arguments */
- char msg[512];
- int ok=1;
- int n=list_length(sc,sc->args);
-
- /* Check number of arguments */
- if(n<pcd->min_arity) {
- ok=0;
- sprintf(msg,"%s: needs%s %d argument(s)",
- pcd->name,
- pcd->min_arity==pcd->max_arity?"":" at least",
- pcd->min_arity);
- }
- if(ok && n>pcd->max_arity) {
- ok=0;
- sprintf(msg,"%s: needs%s %d argument(s)",
- pcd->name,
- pcd->min_arity==pcd->max_arity?"":" at most",
- pcd->max_arity);
- }
- if(ok) {
- if(pcd->arg_tests_encoding!=0) {
- int i=0;
- int j;
- const char *t=pcd->arg_tests_encoding;
- pointer arglist=sc->args;
- do {
- pointer arg=car(arglist);
- j=(int)t[0];
- if(j==TST_INPORT[0]) {
- if(!is_inport(arg)) break;
- } else if(j==TST_OUTPORT[0]) {
- if(!is_outport(arg)) break;
- } else if(j==TST_LIST[0]) {
- if(arg!=sc->NIL && !is_pair(arg)) break;
- } else {
- if(!tests[j].fct(arg)) break;
- }
- if(t[1]!=0) {/* last test is replicated as necessary */
- t++;
- }
- arglist=cdr(arglist);
- i++;
- } while(i<n);
- if(i<n) {
- ok=0;
- sprintf(msg,"%s: argument %d must be: %s",
- pcd->name,
- i+1,
- tests[j].kind);
- }
- }
- }
- if(!ok) {
- if(_Error_1(sc,msg,0)==sc->NIL) {
- return;
- }
- pcd=dispatch_table+sc->op;
- }
- }
- old_op=sc->op;
- if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) {
- return;
- }
- if(sc->no_memory) {
- fprintf(stderr,"No memory!\n");
- return;
- }
- count++;
- }
- }
- /* ========== Initialization of internal keywords ========== */
- static void assign_syntax(scheme *sc, char *name) {
- pointer x;
- x = oblist_add_by_name(sc, name);
- typeflag(x) |= T_SYNTAX;
- }
- static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) {
- pointer x, y;
- x = mk_symbol(sc, name);
- y = mk_proc(sc,op);
- new_slot_in_env(sc, x, y);
- }
- static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
- pointer y;
- y = get_cell(sc, sc->NIL, sc->NIL);
- typeflag(y) = (T_PROC | T_ATOM);
- ivalue_unchecked(y) = (long) op;
- set_integer(y);
- return y;
- }
- /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
- static int syntaxnum(pointer p) {
- const char *s=strvalue(car(p));
- switch(strlength(car(p))) {
- case 2:
- if(s[0]=='i') return OP_IF0; /* if */
- else return OP_OR0; /* or */
- case 3:
- if(s[0]=='a') return OP_AND0; /* and */
- else return OP_LET0; /* let */
- case 4:
- switch(s[3]) {
- case 'e': return OP_CASE0; /* case */
- case 'd': return OP_COND0; /* cond */
- case '*': return OP_LET0AST; /* let* */
- default: return OP_SET0; /* set! */
- }
- case 5:
- switch(s[2]) {
- case 'g': return OP_BEGIN; /* begin */
- case 'l': return OP_DELAY; /* delay */
- case 'c': return OP_MACRO0; /* macro */
- default: return OP_QUOTE; /* quote */
- }
- case 6:
- switch(s[2]) {
- case 'm': return OP_LAMBDA; /* lambda */
- case 'f': return OP_DEF0; /* define */
- default: return OP_LET0REC; /* letrec */
- }
- default:
- return OP_C0STREAM; /* cons-stream */
- }
- }
- /* initialization of TinyScheme */
- #if USE_INTERFACE
- INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
- return cons(sc,a,b);
- }
- INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
- return immutable_cons(sc,a,b);
- }
- static struct scheme_interface vtbl ={
- scheme_define,
- s_cons,
- s_immutable_cons,
- reserve_cells,
- mk_integer,
- mk_real,
- mk_symbol,
- gensym,
- mk_string,
- mk_counted_string,
- mk_character,
- mk_vector,
- mk_foreign_func,
- putstr,
- putcharacter,
- is_string,
- string_value,
- is_number,
- nvalue,
- ivalue,
- rvalue,
- is_integer,
- is_real,
- is_character,
- charvalue,
- is_vector,
- ivalue,
- fill_vector,
- vector_elem,
- set_vector_elem,
- is_port,
- is_pair,
- pair_car,
- pair_cdr,
- set_car,
- set_cdr,
- is_symbol,
- symname,
- is_syntax,
- is_proc,
- is_foreign,
- syntaxname,
- is_closure,
- is_macro,
- closure_code,
- closure_env,
- is_continuation,
- is_promise,
- is_environment,
- is_immutable,
- setimmutable,
- scheme_load_file,
- scheme_load_string
- };
- #endif
- scheme *scheme_init_new() {
- scheme *sc=(scheme*)malloc(sizeof(scheme));
- if(!scheme_init(sc)) {
- free(sc);
- return 0;
- } else {
- return sc;
- }
- }
- scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
- scheme *sc=(scheme*)malloc(sizeof(scheme));
- if(!scheme_init_custom_alloc(sc,malloc,free)) {
- free(sc);
- return 0;
- } else {
- return sc;
- }
- }
- int scheme_init(scheme *sc) {
- return scheme_init_custom_alloc(sc,malloc,free);
- }
- int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
- int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
- pointer x;
- num_zero.is_fixnum=1;
- num_zero.value.ivalue=0;
- num_one.is_fixnum=1;
- num_one.value.ivalue=1;
- #if USE_INTERFACE
- sc->vptr=&vtbl;
- #endif
- sc->gensym_cnt=0;
- sc->malloc=malloc;
- sc->free=free;
- sc->last_cell_seg = -1;
- sc->sink = &sc->_sink;
- sc->NIL = &sc->_NIL;
- sc->T = &sc->_HASHT;
- sc->F = &sc->_HASHF;
- sc->EOF_OBJ=&sc->_EOF_OBJ;
- sc->free_cell = &sc->_NIL;
- sc->fcells = 0;
- sc->no_memory=0;
- sc->inport=sc->NIL;
- sc->outport=sc->NIL;
- sc->save_inport=sc->NIL;
- sc->loadport=sc->NIL;
- sc->nesting=0;
- sc->interactive_repl=0;
-
- if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
- sc->no_memory=1;
- return 0;
- }
- sc->gc_verbose = 0;
- dump_stack_initialize(sc);
- sc->code = sc->NIL;
- sc->tracing=0;
-
- /* init sc->NIL */
- typeflag(sc->NIL) = (T_ATOM | MARK);
- car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
- /* init T */
- typeflag(sc->T) = (T_ATOM | MARK);
- car(sc->T) = cdr(sc->T) = sc->T;
- /* init F */
- typeflag(sc->F) = (T_ATOM | MARK);
- car(sc->F) = cdr(sc->F) = sc->F;
- sc->oblist = oblist_initial_value(sc);
- /* init global_env */
- new_frame_in_env(sc, sc->NIL);
- sc->global_env = sc->envir;
- /* init else */
- x = mk_symbol(sc,"else");
- new_slot_in_env(sc, x, sc->T);
- assign_syntax(sc, "lambda");
- assign_syntax(sc, "quote");
- assign_syntax(sc, "define");
- assign_syntax(sc, "if");
- assign_syntax(sc, "begin");
- assign_syntax(sc, "set!");
- assign_syntax(sc, "let");
- assign_syntax(sc, "let*");
- assign_syntax(sc, "letrec");
- assign_syntax(sc, "cond");
- assign_syntax(sc, "delay");
- assign_syntax(sc, "and");
- assign_syntax(sc, "or");
- assign_syntax(sc, "cons-stream");
- assign_syntax(sc, "macro");
- assign_syntax(sc, "case");
-
- for(i=0; i<n; i++) {
- if(dispatch_table[i].name!=0) {
- assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name);
- }
- }
- /* initialization of global pointers to special symbols */
- sc->LAMBDA = mk_symbol(sc, "lambda");
- sc->QUOTE = mk_symbol(sc, "quote");
- sc->QQUOTE = mk_symbol(sc, "quasiquote");
- sc->UNQUOTE = mk_symbol(sc, "unquote");
- sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
- sc->FEED_TO = mk_symbol(sc, "=>");
- sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
- sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
- sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
- return !sc->no_memory;
- }
- void scheme_set_input_port_file(scheme *sc, FILE *fin) {
- sc->inport=port_from_file(sc,fin,port_input);
- }
- void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
- sc->inport=port_from_string(sc,start,past_the_end,port_input);
- }
- void scheme_set_output_port_file(scheme *sc, FILE *fout) {
- sc->outport=port_from_file(sc,fout,port_output);
- }
- void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
- sc->outport=port_from_string(sc,start,past_the_end,port_output);
- }
- void scheme_set_external_data(scheme *sc, void *p) {
- sc->ext_data=p;
- }
- void scheme_deinit(scheme *sc) {
- int i;
- sc->oblist=sc->NIL;
- sc->global_env=sc->NIL;
- dump_stack_free(sc);
- sc->envir=sc->NIL;
- sc->code=sc->NIL;
- sc->args=sc->NIL;
- sc->value=sc->NIL;
- if(is_port(sc->inport)) {
- typeflag(sc->inport) = T_ATOM;
- }
- sc->inport=sc->NIL;
- sc->outport=sc->NIL;
- if(is_port(sc->save_inport)) {
- typeflag(sc->save_inport) = T_ATOM;
- }
- sc->save_inport=sc->NIL;
- if(is_port(sc->loadport)) {
- typeflag(sc->loadport) = T_ATOM;
- }
- sc->loadport=sc->NIL;
- sc->gc_verbose=0;
- gc(sc,sc->NIL,sc->NIL);
- for(i=0; i<=sc->last_cell_seg; i++) {
- sc->free(sc->alloc_seg[i]);
- }
- }
- void scheme_load_file(scheme *sc, FILE *fin) {
- dump_stack_reset(sc);
- sc->envir = sc->global_env;
- sc->file_i=0;
- sc->load_stack[0].kind=port_input|port_file;
- sc->load_stack[0].rep.stdio.file=fin;
- sc->loadport=mk_port(sc,sc->load_stack);
- sc->retcode=0;
- if(fin==stdin) {
- sc->interactive_repl=1;
- }
- sc->inport=sc->loadport;
- Eval_Cycle(sc, OP_T0LVL);
- typeflag(sc->loadport)=T_ATOM;
- if(sc->retcode==0) {
- sc->retcode=sc->nesting!=0;
- }
- }
- void scheme_load_string(scheme *sc, const char *cmd) {
- dump_stack_reset(sc);
- sc->envir = sc->global_env;
- sc->file_i=0;
- sc->load_stack[0].kind=port_input|port_string;
- sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
- sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
- sc->load_stack[0].rep.string.curr=(char*)cmd;
- sc->loadport=mk_port(sc,sc->load_stack);
- sc->retcode=0;
- sc->interactive_repl=0;
- sc->inport=sc->loadport;
- Eval_Cycle(sc, OP_T0LVL);
- typeflag(sc->loadport)=T_ATOM;
- if(sc->retcode==0) {
- sc->retcode=sc->nesting!=0;
- }
- }
- void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
- pointer x;
- x=find_slot_in_env(sc,envir,symbol,0);
- if (x != sc->NIL) {
- set_slot_in_env(sc, x, value);
- } else {
- new_slot_spec_in_env(sc, envir, symbol, value);
- }
- }
- #if !STANDALONE
- void scheme_apply0(scheme *sc, const char *procname) {
- pointer carx=mk_symbol(sc,procname);
- pointer cdrx=sc->NIL;
- dump_stack_reset(sc);
- sc->envir = sc->global_env;
- sc->code = cons(sc,carx,cdrx);
- sc->interactive_repl=0;
- sc->retcode=0;
- Eval_Cycle(sc,OP_EVAL);
- }
- void scheme_call(scheme *sc, pointer func, pointer args) {
- dump_stack_reset(sc);
- sc->envir = sc->global_env;
- sc->args = args;
- sc->code = func;
- sc->interactive_repl =0;
- sc->retcode = 0;
- Eval_Cycle(sc, OP_APPLY);
- }
- #endif
- /* ========== Main ========== */
- #if STANDALONE
- #if defined(__APPLE__) && !defined (OSX)
- int main()
- {
- extern MacTS_main(int argc, char **argv);
- char** argv;
- int argc = ccommand(&argv);
- MacTS_main(argc,argv);
- return 0;
- }
- int MacTS_main(int argc, char **argv) {
- #else
- int main(int argc, char **argv) {
- #endif
- scheme sc;
- FILE *fin;
- char *file_name=InitFile;
- int retcode;
- int isfile=1;
-
- if(argc==1) {
- printf(banner);
- }
- if(argc==2 && strcmp(argv[1],"-?")==0) {
- printf("Usage: %s [-? | <file1> <file2> ... | -1 <file> <arg1> <arg2> ...]\n\tUse - as filename for stdin.\n",argv[0]);
- return 1;
- }
- if(!scheme_init(&sc)) {
- fprintf(stderr,"Could not initialize!\n");
- return 2;
- }
- scheme_set_input_port_file(&sc, stdin);
- scheme_set_output_port_file(&sc, stdout);
- #if USE_DL
- scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
- #endif
- argv++;
- if(access(file_name,0)!=0) {
- char *p=getenv("TINYSCHEMEINIT");
- if(p!=0) {
- file_name=p;
- }
- }
- do {
- if(strcmp(file_name,"-")==0) {
- fin=stdin;
- } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
- pointer args=sc.NIL;
- isfile=file_name[1]=='1';
- file_name=*argv++;
- if(strcmp(file_name,"-")==0) {
- fin=stdin;
- } else if(isfile) {
- fin=fopen(file_name,"r");
- }
- for(;*argv;argv++) {
- pointer value=mk_string(&sc,*argv);
- args=cons(&sc,value,args);
- }
- args=reverse_in_place(&sc,sc.NIL,args);
- scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
- } else {
- fin=fopen(file_name,"r");
- }
- if(isfile && fin==0) {
- fprintf(stderr,"Could not open file %s\n",file_name);
- } else {
- if(isfile) {
- scheme_load_file(&sc,fin);
- } else {
- scheme_load_string(&sc,file_name);
- }
- if(!isfile || fin!=stdin) {
- if(sc.retcode!=0) {
- fprintf(stderr,"Errors encountered reading %s\n",file_name);
- }
- if(isfile) {
- fclose(fin);
- }
- }
- }
- file_name=*argv++;
- } while(file_name!=0);
- if(argc==1) {
- scheme_load_file(&sc,stdin);
- }
- retcode=sc.retcode;
- scheme_deinit(&sc);
-
- return retcode;
- }
- #endif
|