1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625 |
- #include "limbo.h"
- #include "y.tab.h"
- Node **labstack;
- int labdep;
- static Node* inexcept;
- static Decl* fndec;
- void checkraises(Node *n);
- static void
- increfs(Decl *id)
- {
- for( ; id != nil; id = id->link)
- id->refs++;
- }
- static int
- fninline(Decl *d)
- {
- Node *n, *left, *right;
- left = right = nil;
- n = d->init;
- if(dontinline || d->caninline < 0 || d->locals != nil || ispoly(d) || n->ty->tof->kind == Tnone || nodes(n) >= 100)
- return 0;
- n = n->right;
- if(n->op == Oseq && n->right == nil)
- n = n->left;
- /*
- * inline
- * (a) return e;
- * (b) if(c) return e1; else return e2;
- * (c) if(c) return e1; return e2;
- */
- switch(n->op){
- case Oret:
- break;
- case Oif:
- right = n->right;
- if(right->right == nil || right->left->op != Oret || right->right->op != Oret || !tequal(right->left->left->ty, right->right->left->ty))
- return 0;
- break;
- case Oseq:
- left = n->left;
- right = n->right;
- if(left->op != Oif || left->right->right != nil || left->right->left->op != Oret || right->op != Oseq || right->right != nil || right->left->op != Oret || !tequal(left->right->left->left->ty, right->left->left->ty))
- return 0;
- break;
- default:
- return 0;
- }
- if(occurs(d, n) || hasasgns(n))
- return 0;
- if(n->op == Oseq){
- left->right->right = right->left;
- n = left;
- right = n->right;
- d->init->right->right = nil;
- }
- if(n->op == Oif){
- n->ty = right->ty = right->left->left->ty;
- right->left = right->left->left;
- right->right = right->right->left;
- d->init->right->left = mkunary(Oret, n);
- }
- return 1;
- }
- static int
- isfnrefty(Type *t)
- {
- return t->kind == Tref && t->tof->kind == Tfn;
- }
- static int
- isfnref(Decl *d)
- {
- switch(d->store){
- case Dglobal:
- case Darg:
- case Dlocal:
- case Dfield:
- case Dimport:
- return isfnrefty(d->ty);
- }
- return 0;
- }
- int
- argncompat(Node *n, Decl *f, Node *a)
- {
- for(; a != nil; a = a->right){
- if(f == nil){
- nerror(n, "%V: too many function arguments", n->left);
- return 0;
- }
- f = f->next;
- }
- if(f != nil){
- nerror(n, "%V: too few function arguments", n->left);
- return 0;
- }
- return 1;
- }
- static void
- rewind(Node *n)
- {
- Node *r, *nn;
- r = n;
- nn = n->left;
- for(n = n->right; n != nil; n = n->right){
- if(n->right == nil){
- r->left = nn;
- r->right = n->left;
- }
- else
- nn = mkbin(Oindex, nn, n->left);
- }
- }
- static void
- ckmod(Node *n, Decl *id)
- {
- Type *t;
- Decl *d, *idc;
- Node *mod;
- if(id == nil)
- fatal("can't find function: %n", n);
- idc = nil;
- mod = nil;
- if(n->op == Oname){
- idc = id;
- mod = id->eimport;
- }
- else if(n->op == Omdot)
- mod = n->left;
- else if(n->op == Odot){
- idc = id->dot;
- t = n->left->ty;
- if(t->kind == Tref)
- t = t->tof;
- if(t->kind == Tadtpick)
- t = t->decl->dot->ty;
- d = t->decl;
- while(d != nil && d->link != nil)
- d = d->link;
- if(d != nil && d->timport != nil)
- mod = d->timport->eimport;
- n->right->left = mod;
- }
- if(mod != nil && mod->ty->kind != Tmodule){
- nerror(n, "cannot use %V as a function reference", n);
- return;
- }
- if(mod != nil){
- if(valistype(mod)){
- nerror(n, "cannot use %V as a function reference because %V is a module interface", n, mod);
- return;
- }
- }else if(idc != nil && idc->dot != nil && !isimpmod(idc->dot->sym)){
- nerror(n, "cannot use %V without importing %s from a variable", n, idc->sym->name);
- return;
- }
- if(mod != nil)
- modrefable(n->ty);
- }
- static void
- addref(Node *n)
- {
- Node *nn;
- nn = mkn(0, nil, nil);
- *nn = *n;
- n->op = Oref;
- n->left = nn;
- n->right = nil;
- n->decl = nil;
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Tref, nn->ty, nil));
- }
- static void
- fnref(Node *n, Decl *id)
- {
- id->caninline = -1;
- ckmod(n, id);
- addref(n);
- while(id->link != nil)
- id = id->link;
- if(ispoly(id) && encpolys(id) != nil)
- nerror(n, "cannot have a polymorphic adt function reference %s", id->sym->name);
- }
- Decl*
- typecheck(int checkimp)
- {
- Decl *entry, *m, *d;
- Sym *s;
- int i;
- if(errors)
- return nil;
- /*
- * generate the set of all functions
- * compile one function at a time
- */
- gdecl(tree);
- gbind(tree);
- fns = allocmem(nfns * sizeof(Decl));
- i = gcheck(tree, fns, 0);
- if(i != nfns)
- fatal("wrong number of functions found in gcheck");
- maxlabdep = 0;
- for(i = 0; i < nfns; i++){
- d = fns[i];
- if(d != nil)
- fndec = d;
- if(d != nil)
- fncheck(d);
- fndec = nil;
- }
- if(errors)
- return nil;
- entry = nil;
- if(checkimp){
- Decl *im;
- Dlist *dm;
- if(impmods == nil){
- yyerror("no implementation module");
- return nil;
- }
- for(im = impmods; im != nil; im = im->next){
- for(dm = impdecls; dm != nil; dm = dm->next)
- if(dm->d->sym == im->sym)
- break;
- if(dm == nil || dm->d->ty == nil){
- yyerror("no definition for implementation module %s", im->sym->name);
- return nil;
- }
- }
-
- /*
- * can't check the module spec until all types and imports are determined,
- * which happens in scheck
- */
- for(dm = impdecls; dm != nil; dm = dm->next){
- im = dm->d;
- im->refs++;
- im->ty = usetype(im->ty);
- if(im->store != Dtype || im->ty->kind != Tmodule){
- error(im->src.start, "cannot implement %K", im);
- return nil;
- }
- }
-
- /* now check any multiple implementations */
- impdecl = modimp(impdecls, impmods);
- s = enter("init", 0);
- entry = nil;
- for(dm = impdecls; dm != nil; dm = dm->next){
- im = dm->d;
- for(m = im->ty->ids; m != nil; m = m->next){
- m->ty = usetype(m->ty);
- m->refs++;
-
- if(m->sym == s && m->ty->kind == Tfn && entry == nil)
- entry = m;
-
- if(m->store == Dglobal || m->store == Dfn)
- modrefable(m->ty);
-
- if(m->store == Dtype && m->ty->kind == Tadt){
- for(d = m->ty->ids; d != nil; d = d->next){
- d->ty = usetype(d->ty);
- modrefable(d->ty);
- d->refs++;
- }
- }
- }
- checkrefs(im->ty->ids);
- }
- }
- if(errors)
- return nil;
- gsort(tree);
- tree = nil;
- return entry;
- }
-
- /*
- * introduce all global declarations
- * also adds all fields to adts and modules
- * note the complications due to nested Odas expressions
- */
- void
- gdecl(Node *n)
- {
- for(;;){
- if(n == nil)
- return;
- if(n->op != Oseq)
- break;
- gdecl(n->left);
- n = n->right;
- }
- switch(n->op){
- case Oimport:
- importdecled(n);
- gdasdecl(n->right);
- break;
- case Oadtdecl:
- adtdecled(n);
- break;
- case Ocondecl:
- condecled(n);
- gdasdecl(n->right);
- break;
- case Oexdecl:
- exdecled(n);
- break;
- case Omoddecl:
- moddecled(n);
- break;
- case Otypedecl:
- typedecled(n);
- break;
- case Ovardecl:
- vardecled(n);
- break;
- case Ovardecli:
- vardecled(n->left);
- gdasdecl(n->right);
- break;
- case Ofunc:
- fndecled(n);
- break;
- case Oas:
- case Odas:
- case Onothing:
- gdasdecl(n);
- break;
- default:
- fatal("can't deal with %O in gdecl", n->op);
- }
- }
- /*
- * bind all global type ids,
- * including those nested inside modules
- * this needs to be done, since we may use such
- * a type later in a nested scope, so if we bound
- * the type ids then, the type could get bound
- * to a nested declaration
- */
- void
- gbind(Node *n)
- {
- Decl *d, *ids;
- for(;;){
- if(n == nil)
- return;
- if(n->op != Oseq)
- break;
- gbind(n->left);
- n = n->right;
- }
- switch(n->op){
- case Oas:
- case Ocondecl:
- case Odas:
- case Oexdecl:
- case Ofunc:
- case Oimport:
- case Onothing:
- case Ovardecl:
- case Ovardecli:
- break;
- case Ofielddecl:
- bindtypes(n->decl->ty);
- break;
- case Otypedecl:
- bindtypes(n->decl->ty);
- if(n->left != nil)
- gbind(n->left);
- break;
- case Opickdecl:
- gbind(n->left);
- d = n->right->left->decl;
- bindtypes(d->ty);
- repushids(d->ty->ids);
- gbind(n->right->right);
- /* get new ids for undefined types; propagate outwards */
- ids = popids(d->ty->ids);
- if(ids != nil)
- installids(Dundef, ids);
- break;
- case Oadtdecl:
- case Omoddecl:
- bindtypes(n->ty);
- if(n->ty->polys != nil)
- repushids(n->ty->polys);
- repushids(n->ty->ids);
- gbind(n->left);
- /* get new ids for undefined types; propagate outwards */
- ids = popids(n->ty->ids);
- if(ids != nil)
- installids(Dundef, ids);
- if(n->ty->polys != nil)
- popids(n->ty->polys);
- break;
- default:
- fatal("can't deal with %O in gbind", n->op);
- }
- }
- /*
- * check all of the > declarations
- * bind all type ids referred to within types at the global level
- * record decls for defined functions
- */
- int
- gcheck(Node *n, Decl **fns, int nfns)
- {
- Ok rok;
- Decl *d;
- for(;;){
- if(n == nil)
- return nfns;
- if(n->op != Oseq)
- break;
- nfns = gcheck(n->left, fns, nfns);
- n = n->right;
- }
- switch(n->op){
- case Ofielddecl:
- if(n->decl->ty->u.eraises)
- raisescheck(n->decl->ty);
- break;
- case Onothing:
- case Opickdecl:
- break;
- case Otypedecl:
- tcycle(n->ty);
- break;
- case Oadtdecl:
- case Omoddecl:
- if(n->ty->polys != nil)
- repushids(n->ty->polys);
- repushids(n->ty->ids);
- if(gcheck(n->left, nil, 0))
- fatal("gcheck fn decls nested in modules or adts");
- if(popids(n->ty->ids) != nil)
- fatal("gcheck installs new ids in a module or adt");
- if(n->ty->polys != nil)
- popids(n->ty->polys);
- break;
- case Ovardecl:
- varcheck(n, 1);
- break;
- case Ocondecl:
- concheck(n, 1);
- break;
- case Oexdecl:
- excheck(n, 1);
- break;
- case Oimport:
- importcheck(n, 1);
- break;
- case Ovardecli:
- varcheck(n->left, 1);
- rok = echeck(n->right, 0, 1, nil);
- if(rok.ok){
- if(rok.allok)
- n->right = fold(n->right);
- globalas(n->right->left, n->right->right, rok.allok);
- }
- break;
- case Oas:
- case Odas:
- rok = echeck(n, 0, 1, nil);
- if(rok.ok){
- if(rok.allok)
- n = fold(n);
- globalas(n->left, n->right, rok.allok);
- }
- break;
- case Ofunc:
- rok = echeck(n->left, 0, 1, n);
- if(rok.ok && n->ty->u.eraises)
- raisescheck(n->ty);
- d = nil;
- if(rok.ok)
- d = fnchk(n);
- fns[nfns++] = d;
- break;
- default:
- fatal("can't deal with %O in gcheck", n->op);
- }
- return nfns;
- }
- /*
- * check for unused expression results
- * make sure the any calculated expression has
- * a destination
- */
- Node*
- checkused(Node *n)
- {
- Type *t;
- Node *nn;
- /*
- * only nil; and nil = nil; should have type tany
- */
- if(n->ty == tany){
- if(n->op == Oname)
- return n;
- if(n->op == Oas)
- return checkused(n->right);
- fatal("line %L checkused %n", n->src.start, n);
- }
- if(n->op == Ocall && n->left->ty->kind == Tfn && n->left->ty->tof != tnone){
- n = mkunary(Oused, n);
- n->ty = n->left->ty;
- return n;
- }
- if(n->op == Ocall && isfnrefty(n->left->ty)){
- if(n->left->ty->tof->tof != tnone){
- n = mkunary(Oused, n);
- n->ty = n->left->ty;
- }
- return n;
- }
- if(isused[n->op] && (n->op != Ocall || n->left->ty->kind == Tfn))
- return n;
- t = n->ty;
- if(t->kind == Tfn)
- nerror(n, "function %V not called", n);
- else if(t->kind == Tadt && t->tags != nil || t->kind == Tadtpick)
- nerror(n, "expressions cannot have type %T", t);
- else if(n->op == Otuple){
- for(nn = n->left; nn != nil; nn = nn->right)
- checkused(nn->left);
- }
- else
- nwarn(n, "result of expression %V not used", n);
- n = mkunary(Oused, n);
- n->ty = n->left->ty;
- return n;
- }
- void
- fncheck(Decl *d)
- {
- Node *n;
- Decl *adtp;
- n = d->init;
- if(debug['t'])
- print("typecheck tree: %n\n", n);
- fndecls = nil;
- adtp = outerpolys(n->left);
- if(n->left->op == Odot)
- repushids(adtp);
- if(d->ty->polys != nil)
- repushids(d->ty->polys);
- repushids(d->ty->ids);
- labdep = 0;
- labstack = allocmem(maxlabdep * sizeof *labstack);
- n->right = scheck(n->right, d->ty->tof, Sother);
- if(labdep != 0)
- fatal("unbalanced label stack in fncheck");
- free(labstack);
- d->locals = appdecls(popids(d->ty->ids), fndecls);
- if(d->ty->polys != nil)
- popids(d->ty->polys);
- if(n->left->op == Odot)
- popids(adtp);
- fndecls = nil;
- checkrefs(d->ty->ids);
- checkrefs(d->ty->polys);
- checkrefs(d->locals);
- checkraises(n);
- d->caninline = fninline(d);
- }
- Node*
- scheck(Node *n, Type *ret, int kind)
- {
- Node *left, *right, *last, *top;
- Decl *d;
- Sym *s;
- Ok rok;
- int i;
- top = n;
- last = nil;
- for(; n != nil; n = n->right){
- left = n->left;
- right = n->right;
- switch(n->op){
- case Ovardecl:
- vardecled(n);
- varcheck(n, 0);
- if (nested() && tmustzero(n->decl->ty))
- decltozero(n);
- /*
- else if (inloop() && tmustzero(n->decl->ty))
- decltozero(n);
- */
- return top;
- case Ovardecli:
- vardecled(left);
- varcheck(left, 0);
- echeck(right, 0, 0, nil);
- if (nested() && tmustzero(left->decl->ty))
- decltozero(left);
- return top;
- case Otypedecl:
- typedecled(n);
- bindtypes(n->ty);
- tcycle(n->ty);
- return top;
- case Ocondecl:
- condecled(n);
- concheck(n, 0);
- return top;
- case Oexdecl:
- exdecled(n);
- excheck(n, 0);
- return top;
- case Oimport:
- importdecled(n);
- importcheck(n, 0);
- return top;
- case Ofunc:
- fatal("scheck func");
- case Oscope:
- pushscope(n, kind == Sother ? Sscope : kind);
- if (left != nil)
- fatal("Oscope has left field");
- echeck(left, 0, 0, nil);
- n->right = scheck(right, ret, Sother);
- d = popscope();
- fndecls = appdecls(fndecls, d);
- return top;
- case Olabel:
- echeck(left, 0, 0, nil);
- n->right = scheck(right, ret, Sother);
- return top;
- case Oseq:
- n->left = scheck(left, ret, Sother);
- /* next time will check n->right */
- break;
- case Oif:
- rok = echeck(left, 0, 0, nil);
- if(rok.ok && left->op != Onothing && left->ty != tint)
- nerror(n, "if conditional must be an int, not %Q", left);
- right->left = scheck(right->left, ret, Sother);
- /* next time will check n->right->right */
- n = right;
- break;
- case Ofor:
- rok = echeck(left, 0, 0, nil);
- if(rok.ok && left->op != Onothing && left->ty != tint)
- nerror(n, "for conditional must be an int, not %Q", left);
- /*
- * do the continue clause before the body
- * this reflects the ordering of declarations
- */
- pushlabel(n);
- right->right = scheck(right->right, ret, Sother);
- right->left = scheck(right->left, ret, Sloop);
- labdep--;
- if(n->decl != nil && !n->decl->refs)
- nwarn(n, "label %s never referenced", n->decl->sym->name);
- return top;
- case Odo:
- rok = echeck(left, 0, 0, nil);
- if(rok.ok && left->op != Onothing && left->ty != tint)
- nerror(n, "do conditional must be an int, not %Q", left);
- pushlabel(n);
- n->right = scheck(n->right, ret, Sloop);
- labdep--;
- if(n->decl != nil && !n->decl->refs)
- nwarn(n, "label %s never referenced", n->decl->sym->name);
- return top;
- case Oalt:
- case Ocase:
- case Opick:
- case Oexcept:
- pushlabel(n);
- switch(n->op){
- case Oalt:
- altcheck(n, ret);
- break;
- case Ocase:
- casecheck(n, ret);
- break;
- case Opick:
- pickcheck(n, ret);
- break;
- case Oexcept:
- exccheck(n, ret);
- break;
- }
- labdep--;
- if(n->decl != nil && !n->decl->refs)
- nwarn(n, "label %s never referenced", n->decl->sym->name);
- return top;
- case Oret:
- rok = echeck(left, 0, 0, nil);
- if(!rok.ok)
- return top;
- if(left == nil){
- if(ret != tnone)
- nerror(n, "return of nothing from a fn of %T", ret);
- }else if(ret == tnone){
- if(left->ty != tnone)
- nerror(n, "return %Q from a fn with no return type", left);
- }else if(!tcompat(ret, left->ty, 0))
- nerror(n, "return %Q from a fn of %T", left, ret);
- return top;
- case Obreak:
- case Ocont:
- s = nil;
- if(n->decl != nil)
- s = n->decl->sym;
- for(i = 0; i < labdep; i++){
- if(s == nil || labstack[i]->decl != nil && labstack[i]->decl->sym == s){
- if(n->op == Ocont
- && labstack[i]->op != Ofor && labstack[i]->op != Odo)
- continue;
- if(s != nil)
- labstack[i]->decl->refs++;
- return top;
- }
- }
- nerror(n, "no appropriate target for %V", n);
- return top;
- case Oexit:
- case Onothing:
- return top;
- case Oexstmt:
- fndec->handler = 1;
- n->left = scheck(left, ret, Sother);
- n->right = scheck(right, ret, Sother);
- return top;
- default:
- rok = echeck(n, 0, 0, nil);
- if(rok.allok)
- n = checkused(n);
- if(last == nil)
- return n;
- last->right = n;
- return top;
- }
- last = n;
- }
- return top;
- }
- void
- pushlabel(Node *n)
- {
- Sym *s;
- int i;
- if(labdep >= maxlabdep){
- maxlabdep += MaxScope;
- labstack = reallocmem(labstack, maxlabdep * sizeof *labstack);
- }
- if(n->decl != nil){
- s = n->decl->sym;
- n->decl->refs = 0;
- for(i = 0; i < labdep; i++)
- if(labstack[i]->decl != nil && labstack[i]->decl->sym == s)
- nerror(n, "label %s duplicated on line %L", s->name, labstack[i]->decl->src.start);
- }
- labstack[labdep++] = n;
- }
- void
- varcheck(Node *n, int isglobal)
- {
- Type *t;
- Decl *ids, *last;
- t = validtype(n->ty, nil);
- t = topvartype(t, n->decl, isglobal, 0);
- last = n->left->decl;
- for(ids = n->decl; ids != last->next; ids = ids->next){
- ids->ty = t;
- shareloc(ids);
- }
- if(t->u.eraises)
- raisescheck(t);
- }
- void
- concheck(Node *n, int isglobal)
- {
- Decl *ids, *last;
- Type *t;
- Node *init;
- Ok rok;
- int i;
- pushscope(nil, Sother);
- installids(Dconst, iota);
- rok = echeck(n->right, 0, isglobal, nil);
- popscope();
- init = n->right;
- if(!rok.ok){
- t = terror;
- }else{
- t = init->ty;
- if(!tattr[t->kind].conable){
- nerror(init, "cannot have a %T constant", t);
- rok.allok = 0;
- }
- }
- last = n->left->decl;
- for(ids = n->decl; ids != last->next; ids = ids->next)
- ids->ty = t;
- if(!rok.allok)
- return;
- i = 0;
- for(ids = n->decl; ids != last->next; ids = ids->next){
- if(rok.ok){
- iota->init->val = i;
- ids->init = dupn(0, &nosrc, init);
- if(!varcom(ids))
- rok.ok = 0;
- }
- i++;
- }
- }
- static char*
- exname(Decl *d)
- {
- int n;
- Sym *m;
- char *s;
- char buf[16];
- n = 0;
- sprint(buf, "%d", scope-ScopeGlobal);
- m = impmods->sym;
- if(d->dot)
- m = d->dot->sym;
- if(m)
- n += strlen(m->name)+1;
- if(fndec)
- n += strlen(fndec->sym->name)+1;
- n += strlen(buf)+1+strlen(d->sym->name)+1;
- s = malloc(n);
- strcpy(s, "");
- if(m){
- strcat(s, m->name);
- strcat(s, ".");
- }
- if(fndec){
- strcat(s, fndec->sym->name);
- strcat(s, ".");
- }
- strcat(s, buf);
- strcat(s, ".");
- strcat(s, d->sym->name);
- return s;
- }
- void
- excheck(Node *n, int isglobal)
- {
- char *nm;
- Type *t;
- Decl *ids, *last;
- t = validtype(n->ty, nil);
- t = topvartype(t, n->decl, isglobal, 0);
- last = n->left->decl;
- for(ids = n->decl; ids != last->next; ids = ids->next){
- ids->ty = t;
- nm = exname(ids);
- ids->init = mksconst(&n->src, enterstring(nm, strlen(nm)));
- /* ids->init = mksconst(&n->src, enterstring(strdup(ids->sym->name), strlen(ids->sym->name))); */
- }
- }
- void
- importcheck(Node *n, int isglobal)
- {
- Node *m;
- Decl *id, *last, *v;
- Type *t;
- Ok rok;
- rok = echeck(n->right, 1, isglobal, nil);
- if(!rok.ok)
- return;
- m = n->right;
- if(m->ty->kind != Tmodule || m->op != Oname){
- nerror(n, "cannot import from %Q", m);
- return;
- }
- last = n->left->decl;
- for(id = n->decl; id != last->next; id = id->next){
- v = namedot(m->ty->ids, id->sym);
- if(v == nil){
- error(id->src.start, "%s is not a member of %V", id->sym->name, m);
- id->store = Dwundef;
- continue;
- }
- id->store = v->store;
- v->ty = validtype(v->ty, nil);
- id->ty = t = v->ty;
- if(id->store == Dtype && t->decl != nil){
- id->timport = t->decl->timport;
- t->decl->timport = id;
- }
- id->init = v->init;
- id->importid = v;
- id->eimport = m;
- }
- }
- static Decl*
- rewcall(Node *n, Decl *d)
- {
- /* put original function back now we're type checked */
- while(d->link != nil)
- d = d->link;
- if(n->op == Odot)
- n->right->decl = d;
- else if(n->op == Omdot){
- n->right->right->decl = d;
- n->right->right->ty = d->ty;
- }
- else
- fatal("bad op in Ocall rewcall");
- n->ty = n->right->ty = d->ty;
- d->refs++;
- usetype(d->ty);
- return d;
- }
- /*
- * annotate the expression with types
- */
- Ok
- echeck(Node *n, int typeok, int isglobal, Node *par)
- {
- Type *t, *tt;
- Node *left, *right, *mod, *nn;
- Decl *tg, *id, *callee;
- Sym *s;
- int max, nocheck;
- Ok ok, rok, kidsok;
- static int tagopt;
- ok.ok = ok.allok = 1;
- if(n == nil)
- return ok;
-
- /* avoid deep recursions */
- if(n->op == Oseq){
- for( ; n != nil && n->op == Oseq; n = n->right){
- rok = echeck(n->left, typeok == 2, isglobal, n);
- ok.ok &= rok.ok;
- ok.allok &= rok.allok;
- n->ty = tnone;
- }
- if(n == nil)
- return ok;
- }
- left = n->left;
- right = n->right;
- nocheck = 0;
- if(n->op == Odot || n->op == Omdot || n->op == Ocall || n->op == Oref || n->op == Otagof || n->op == Oindex)
- nocheck = 1;
- if(n->op != Odas /* special case */
- && n->op != Oload) /* can have better error recovery */
- ok = echeck(left, nocheck, isglobal, n);
- if(n->op != Odas /* special case */
- && n->op != Odot /* special check */
- && n->op != Omdot /* special check */
- && n->op != Ocall /* can have better error recovery */
- && n->op != Oindex){
- rok = echeck(right, 0, isglobal, n);
- ok.ok &= rok.ok;
- ok.allok &= rok.allok;
- }
- if(!ok.ok){
- n->ty = terror;
- ok.allok = 0;
- return ok;
- }
- switch(n->op){
- case Odas:
- kidsok = echeck(right, 0, isglobal, n);
- if(!kidsok.ok)
- right->ty = terror;
- if(!isglobal && !dasdecl(left)){
- kidsok.ok = 0;
- }else if(!specific(right->ty) || !declasinfer(left, right->ty)){
- nerror(n, "cannot declare %V from %Q", left, right);
- declaserr(left);
- kidsok.ok = 0;
- }
- if(right->ty->kind == Texception)
- left->ty = n->ty = mkextuptype(right->ty);
- else{
- left->ty = n->ty = right->ty;
- usedty(n->ty);
- }
- kidsok.allok &= kidsok.ok;
- if (nested() && tmustzero(left->ty))
- decltozero(left);
- return kidsok;
- case Oseq:
- case Onothing:
- n->ty = tnone;
- break;
- case Owild:
- n->ty = tint;
- break;
- case Ocast:
- t = usetype(n->ty);
- n->ty = t;
- tt = left->ty;
- if(tcompat(t, tt, 0)){
- left->ty = t;
- break;
- }
- if(tt->kind == Tarray){
- if(tt->tof == tbyte && t == tstring)
- break;
- }else if(t->kind == Tarray){
- if(t->tof == tbyte && tt == tstring)
- break;
- }else if(casttab[tt->kind][t->kind]){
- break;
- }
- nerror(n, "cannot make a %T from %Q", n->ty, left);
- ok.ok = ok.allok = 0;
- return ok;
- case Ochan:
- n->ty = usetype(n->ty);
- if(left && left->ty->kind != Tint){
- nerror(n, "channel size %Q is not an int", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Oload:
- n->ty = usetype(n->ty);
- kidsok = echeck(left, 0, isglobal, n);
- if(n->ty->kind != Tmodule){
- nerror(n, "cannot load a %T, ", n->ty);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(!kidsok.allok){
- ok.allok = 0;
- break;
- }
- if(left->ty != tstring){
- nerror(n, "cannot load a module from %Q", left);
- ok.allok = 0;
- break;
- }
- if(n->ty->tof->decl->refs != 0)
- n->ty->tof->decl->refs++;
- n->ty->decl->refs++;
- usetype(n->ty->tof);
- break;
- case Oref:
- t = left->ty;
- if(t->kind != Tadt && t->kind != Tadtpick && t->kind != Tfn && t->kind != Ttuple){
- nerror(n, "cannot make a ref from %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(!tagopt && t->kind == Tadt && t->tags != nil && valistype(left)){
- nerror(n, "instances of ref %V must be qualified with a pick tag", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(t->kind == Tadtpick)
- t->tof = usetype(t->tof);
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Tref, t, nil));
- break;
- case Oarray:
- max = 0;
- if(right != nil){
- max = assignindices(n);
- if(max < 0){
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(!specific(right->left->ty)){
- nerror(n, "type for array not specific");
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = mktype(&n->src.start, &n->src.stop, Tarray, right->left->ty, nil);
- }
- n->ty = usetype(n->ty);
- if(left->op == Onothing)
- n->left = left = mkconst(&n->left->src, max);
- if(left->ty->kind != Tint){
- nerror(n, "array size %Q is not an int", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Oelem:
- n->ty = right->ty;
- break;
- case Orange:
- if(left->ty != right->ty
- || left->ty != tint && left->ty != tstring){
- nerror(left, "range %Q to %Q is not an int or string range", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = left->ty;
- break;
- case Oname:
- id = n->decl;
- if(id == nil){
- nerror(n, "name with no declaration");
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->store == Dunbound){
- s = id->sym;
- id = s->decl;
- if(id == nil)
- id = undefed(&n->src, s);
- /* save a little space */
- s->unbound = nil;
- n->decl = id;
- id->refs++;
- }
- n->ty = id->ty = usetype(id->ty);
- switch(id->store){
- case Dfn:
- case Dglobal:
- case Darg:
- case Dlocal:
- case Dimport:
- case Dfield:
- case Dtag:
- break;
- case Dundef:
- nerror(n, "%s is not declared", id->sym->name);
- id->store = Dwundef;
- ok.ok = ok.allok = 0;
- return ok;
- case Dwundef:
- ok.ok = ok.allok = 0;
- return ok;
- case Dconst:
- if(id->init == nil){
- nerror(n, "%s's value cannot be determined", id->sym->name);
- id->store = Dwundef;
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Dtype:
- if(typeok)
- break;
- nerror(n, "%K is not a variable", id);
- ok.ok = ok.allok = 0;
- return ok;
- default:
- fatal("echeck: unknown symbol storage");
- }
-
- if(n->ty == nil){
- nerror(n, "%K's type is not fully defined", id);
- id->store = Dwundef;
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->importid != nil && valistype(id->eimport)
- && id->store != Dconst && id->store != Dtype && id->store != Dfn){
- nerror(n, "cannot use %V because %V is a module interface", n, id->eimport);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(n->ty->kind == Texception && !n->ty->cons && par != nil && par->op != Oraise && par->op != Odot){
- nn = mkn(0, nil, nil);
- *nn = *n;
- n->op = Ocast;
- n->left = nn;
- n->decl = nil;
- n->ty = usetype(mkextuptype(n->ty));
- }
- /* function name as function reference */
- if(id->store == Dfn && (par == nil || (par->op != Odot && par->op != Omdot && par->op != Ocall && par->op != Ofunc)))
- fnref(n, id);
- break;
- case Oconst:
- if(n->ty == nil){
- nerror(n, "no type in %V", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Oas:
- t = right->ty;
- if(t->kind == Texception)
- t = mkextuptype(t);
- if(!tcompat(left->ty, t, 1)){
- nerror(n, "type clash in %Q = %Q", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(t == tany)
- t = left->ty;
- n->ty = t;
- left->ty = t;
- if(t->kind == Tadt && t->tags != nil || t->kind == Tadtpick)
- if(left->ty->kind != Tadtpick || right->ty->kind != Tadtpick)
- nerror(n, "expressions cannot have type %T", t);
- if(left->ty->kind == Texception){
- nerror(n, "cannot assign to an exception");
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(islval(left))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Osnd:
- if(left->ty->kind != Tchan){
- nerror(n, "cannot send on %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(!tcompat(left->ty->tof, right->ty, 0)){
- nerror(n, "type clash in %Q <-= %Q", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- t = right->ty;
- if(t == tany)
- t = left->ty->tof;
- n->ty = t;
- break;
- case Orcv:
- t = left->ty;
- if(t->kind == Tarray)
- t = t->tof;
- if(t->kind != Tchan){
- nerror(n, "cannot receive on %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(left->ty->kind == Tarray)
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Ttuple, nil,
- mkids(&n->src, nil, tint, mkids(&n->src, nil, t->tof, nil))));
- else
- n->ty = t->tof;
- break;
- case Ocons:
- if(right->ty->kind != Tlist && right->ty != tany){
- nerror(n, "cannot :: to %Q", right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = right->ty;
- if(right->ty == tany)
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Tlist, left->ty, nil));
- else if(!tcompat(right->ty->tof, left->ty, 0)){
- t = tparent(right->ty->tof, left->ty);
- if(!tcompat(t, left->ty, 0)){
- nerror(n, "type clash in %Q :: %Q", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- else
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Tlist, t, nil));
- }
- break;
- case Ohd:
- case Otl:
- if(left->ty->kind != Tlist || left->ty->tof == nil){
- nerror(n, "cannot %O %Q", n->op, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(n->op == Ohd)
- n->ty = left->ty->tof;
- else
- n->ty = left->ty;
- break;
- case Otuple:
- n->ty = usetype(mktype(&n->src.start, &n->src.stop, Ttuple, nil, tuplefields(left)));
- break;
- case Ospawn:
- if(left->op != Ocall || left->left->ty->kind != Tfn && !isfnrefty(left->left->ty)){
- nerror(left, "cannot spawn %V", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(left->ty != tnone){
- nerror(left, "cannot spawn functions which return values, such as %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Oraise:
- if(left->op == Onothing){
- if(inexcept == nil){
- nerror(n, "%V: empty raise not in exception handler", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->left = dupn(1, &n->src, inexcept);
- break;
- }
- if(left->ty != tstring && left->ty->kind != Texception){
- nerror(n, "%V: raise argument %Q is not a string or exception", n, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if((left->op != Ocall || left->left->ty->kind == Tfn) && left->ty->ids != nil && left->ty->cons){
- nerror(n, "too few exception arguments");
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Ocall:{
- int pure;
- kidsok = echeck(right, 0, isglobal, nil);
- t = left->ty;
- usedty(t);
- pure = 1;
- if(t->kind == Tref){
- pure = 0;
- t = t->tof;
- }
- if(t->kind != Tfn)
- return callcast(n, kidsok.allok, ok.allok);
- n->ty = t->tof;
- if(!kidsok.allok){
- ok.allok = 0;
- break;
- }
- /*
- * get the name to call and any associated module
- */
- mod = nil;
- callee = nil;
- id = nil;
- tt = nil;
- if(left->op == Odot){
- Decl *dd;
- Type *ttt;
- callee = left->right->decl;
- id = callee->dot;
- right = passimplicit(left, right);
- n->right = right;
- tt = left->left->ty;
- if(tt->kind == Tref)
- tt = tt->tof;
- ttt = tt;
- if(tt->kind == Tadtpick)
- ttt = tt->decl->dot->ty;
- dd = ttt->decl;
- while(dd != nil && dd->link != nil)
- dd = dd->link;
- if(dd != nil && dd->timport != nil)
- mod = dd->timport->eimport;
- /*
- * stash the import module under a rock,
- * because we won't be able to get it later
- * after scopes are popped
- */
- left->right->left = mod;
- }else if(left->op == Omdot){
- if(left->right->op == Odot){
- callee = left->right->right->decl;
- right = passimplicit(left->right, right);
- n->right = right;
- tt = left->right->left->ty;
- if(tt->kind == Tref)
- tt = tt->tof;
- }else
- callee = left->right->decl;
- mod = left->left;
- }else if(left->op == Oname){
- callee = left->decl;
- id = callee;
- mod = id->eimport;
- }else if(pure){
- nerror(left, "%V is not a function name", left);
- ok.allok = 0;
- break;
- }
- if(pure && callee == nil)
- fatal("can't find called function: %n", left);
- if(callee != nil && callee->store != Dfn && !isfnref(callee)){
- nerror(left, "%V is not a function or function reference", left);
- ok.allok = 0;
- break;
- }
- if(mod != nil && mod->ty->kind != Tmodule){
- nerror(left, "cannot call %V", left);
- ok.allok = 0;
- break;
- }
- if(mod != nil){
- if(valistype(mod)){
- nerror(left, "cannot call %V because %V is a module interface", left, mod);
- ok.allok = 0;
- break;
- }
- }else if(id != nil && id->dot != nil && !isimpmod(id->dot->sym)){
- nerror(left, "cannot call %V without importing %s from a variable", left, id->sym->name);
- ok.allok = 0;
- break;
- }
- if(mod != nil)
- modrefable(left->ty);
- if(callee != nil && callee->store != Dfn)
- callee = nil;
- if(t->varargs != 0){
- t = mkvarargs(left, right);
- if(left->ty->kind == Tref)
- left->ty = usetype(mktype(&t->src.start, &t->src.stop, Tref, t, nil));
- else
- left->ty = t;
- }
- else if(ispoly(callee) || isfnrefty(left->ty) && left->ty->tof->polys != nil){
- Tpair *tp;
- unifysrc = n->src;
- if(!argncompat(n, t->ids, right))
- ok.allok = 0;
- else if(!tunify(left->ty, calltype(left->ty, right, n->ty), &tp)){
- nerror(n, "function call type mismatch");
- ok.allok = 0;
- }
- else{
- n->ty = usetype(expandtype(n->ty, nil, nil, &tp));
- if(ispoly(callee) && tt != nil && (tt->kind == Tadt || tt->kind == Tadtpick) && (tt->flags&INST))
- callee = rewcall(left, callee);
- n->right = passfns(&n->src, callee, left, right, tt, tp);
- }
- }
- else if(!argcompat(n, t->ids, right))
- ok.allok = 0;
- break;
- }
- case Odot:
- t = left->ty;
- if(t->kind == Tref)
- t = t->tof;
- switch(t->kind){
- case Tadt:
- case Tadtpick:
- case Ttuple:
- case Texception:
- case Tpoly:
- id = namedot(t->ids, right->decl->sym);
- if(id == nil){
- id = namedot(t->tags, right->decl->sym);
- if(id != nil && !valistype(left)){
- nerror(n, "%V is not a type", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- }
- if(id == nil){
- id = namedot(t->polys, right->decl->sym);
- if(id != nil && !valistype(left)){
- nerror(n, "%V is not a type", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- }
- if(id == nil && t->kind == Tadtpick)
- id = namedot(t->decl->dot->ty->ids, right->decl->sym);
- if(id == nil){
- for(tg = t->tags; tg != nil; tg = tg->next){
- id = namedot(tg->ty->ids, right->decl->sym);
- if(id != nil)
- break;
- }
- if(id != nil){
- nerror(n, "cannot yet index field %s of %Q", right->decl->sym->name, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- }
- if(id == nil)
- break;
- if(id->store == Dfield && valistype(left)){
- nerror(n, "%V is not a value", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- id->ty = validtype(id->ty, t->decl);
- id->ty = usetype(id->ty);
- break;
- default:
- nerror(left, "%Q cannot be qualified with .", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id == nil){
- nerror(n, "%V is not a member of %Q", right, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->ty == tunknown){
- nerror(n, "illegal forward reference to %V", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- increfs(id);
- right->decl = id;
- n->ty = id->ty;
- if((id->store == Dconst || id->store == Dtag) && hasside(left, 1))
- nwarn(left, "result of expression %Q ignored", left);
- /* function name as function reference */
- if(id->store == Dfn && (par == nil || (par->op != Omdot && par->op != Ocall && par->op != Ofunc)))
- fnref(n, id);
- break;
- case Omdot:
- t = left->ty;
- if(t->kind != Tmodule){
- nerror(left, "%Q cannot be qualified with ->", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- id = nil;
- if(right->op == Oname){
- id = namedot(t->ids, right->decl->sym);
- }else if(right->op == Odot){
- kidsok = echeck(right, 0, isglobal, n);
- ok.ok = kidsok.ok;
- ok.allok &= kidsok.allok;
- if(!ok.ok){
- ok.allok = 0;
- return ok;
- }
- tt = right->left->ty;
- if(tt->kind == Tref)
- tt = tt->tof;
- if(right->ty->kind == Tfn
- && tt->kind == Tadt
- && tt->decl->dot == t->decl)
- id = right->right->decl;
- }
- if(id == nil){
- nerror(n, "%V is not a member of %Q", right, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->store != Dconst && id->store != Dtype && id->store != Dtag){
- if(valistype(left)){
- nerror(n, "%V is not a value", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- }else if(hasside(left, 1))
- nwarn(left, "result of expression %Q ignored", left);
- if(!typeok && id->store == Dtype){
- nerror(n, "%V is a type, not a value", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->ty == tunknown){
- nerror(n, "illegal forward reference to %V", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- id->refs++;
- right->decl = id;
- n->ty = id->ty = usetype(id->ty);
- if(id->store == Dglobal)
- modrefable(id->ty);
- /* function name as function reference */
- if(id->store == Dfn && (par == nil || (par->op != Ocall && par->op != Ofunc)))
- fnref(n, id);
- break;
- case Otagof:
- n->ty = tint;
- t = left->ty;
- if(t->kind == Tref)
- t = t->tof;
- id = nil;
- switch(left->op){
- case Oname:
- id = left->decl;
- break;
- case Odot:
- id = left->right->decl;
- break;
- case Omdot:
- if(left->right->op == Odot)
- id = left->right->right->decl;
- break;
- }
- if(id != nil && id->store == Dtag
- || id != nil && id->store == Dtype && t->kind == Tadt && t->tags != nil)
- n->decl = id;
- else if(t->kind == Tadt && t->tags != nil || t->kind == Tadtpick)
- n->decl = nil;
- else{
- nerror(n, "cannot get the tag value for %Q", left);
- ok.ok = 1;
- ok.allok = 0;
- return ok;
- }
- break;
- case Oind:
- t = left->ty;
- if(t->kind != Tref || (t->tof->kind != Tadt && t->tof->kind != Tadtpick && t->tof->kind != Ttuple)){
- nerror(n, "cannot * %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = t->tof;
- for(tg = t->tof->tags; tg != nil; tg = tg->next)
- tg->ty->tof = usetype(tg->ty->tof);
- break;
- case Oindex:
- if(valistype(left)){
- tagopt = 1;
- kidsok = echeck(right, 2, isglobal, n);
- tagopt = 0;
- if(!kidsok.allok){
- ok.ok = ok.allok = 0;
- return ok;
- }
- if((t = exptotype(n)) == nil){
- nerror(n, "%V is not a type list", right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(!typeok){
- nerror(n, "%Q is not a variable", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- *n = *(n->left);
- n->ty = usetype(t);
- break;
- }
- if(0 && right->op == Oseq){ /* a[e1, e2, ...] */
- /* array creation to do before we allow this */
- rewind(n);
- return echeck(n, typeok, isglobal, par);
- }
- t = left->ty;
- kidsok = echeck(right, 0, isglobal, n);
- if(t->kind != Tarray && t != tstring){
- nerror(n, "cannot index %Q", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(t == tstring){
- n->op = Oinds;
- n->ty = tint;
- }else{
- n->ty = t->tof;
- }
- if(!kidsok.allok){
- ok.allok = 0;
- break;
- }
- if(right->ty != tint){
- nerror(n, "cannot index %Q with %Q", left, right);
- ok.allok = 0;
- break;
- }
- break;
- case Oslice:
- t = n->ty = left->ty;
- if(t->kind != Tarray && t != tstring){
- nerror(n, "cannot slice %Q with '%v:%v'", left, right->left, right->right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(right->left->ty != tint && right->left->op != Onothing
- || right->right->ty != tint && right->right->op != Onothing){
- nerror(n, "cannot slice %Q with '%v:%v'", left, right->left, right->right);
- ok.allok = 0;
- return ok;
- }
- break;
- case Olen:
- t = left->ty;
- n->ty = tint;
- if(t->kind != Tarray && t->kind != Tlist && t != tstring){
- nerror(n, "len requires an array, string or list in %Q", left);
- ok.allok = 0;
- return ok;
- }
- break;
- case Ocomp:
- case Onot:
- case Oneg:
- n->ty = left->ty;
- usedty(n->ty);
- switch(left->ty->kind){
- case Tint:
- return ok;
- case Treal:
- case Tfix:
- if(n->op == Oneg)
- return ok;
- break;
- case Tbig:
- case Tbyte:
- if(n->op == Oneg || n->op == Ocomp)
- return ok;
- break;
- }
- nerror(n, "cannot apply %O to %Q", n->op, left);
- ok.ok = ok.allok = 0;
- return ok;
- case Oinc:
- case Odec:
- case Opreinc:
- case Opredec:
- n->ty = left->ty;
- switch(left->ty->kind){
- case Tint:
- case Tbig:
- case Tbyte:
- case Treal:
- break;
- default:
- nerror(n, "cannot apply %O to %Q", n->op, left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(islval(left))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Oadd:
- case Odiv:
- case Omul:
- case Osub:
- if(mathchk(n, 1))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Oexp:
- case Oexpas:
- n->ty = left->ty;
- if(n->ty != tint && n->ty != tbig && n->ty != treal){
- nerror(n, "exponend %Q is not int, big or real", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(right->ty != tint){
- nerror(n, "exponent %Q is not int", right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(n->op == Oexpas && !islval(left)){
- ok.ok = ok.allok = 0;
- return ok;
- }
- break;
- case Olsh:
- case Orsh:
- if(shiftchk(n))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Oandand:
- case Ooror:
- if(left->ty != tint){
- nerror(n, "%O's left operand is not an int: %Q", n->op, left);
- ok.allok = 0;
- }
- if(right->ty != tint){
- nerror(n, "%O's right operand is not an int: %Q", n->op, right);
- ok.allok = 0;
- }
- n->ty = tint;
- break;
- case Oand:
- case Omod:
- case Oor:
- case Oxor:
- if(mathchk(n, 0))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Oaddas:
- case Odivas:
- case Omulas:
- case Osubas:
- if(mathchk(n, 1) && islval(left))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Olshas:
- case Orshas:
- if(shiftchk(n) && islval(left))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Oandas:
- case Omodas:
- case Oxoras:
- case Ooras:
- if(mathchk(n, 0) && islval(left))
- break;
- ok.ok = ok.allok = 0;
- return ok;
- case Olt:
- case Oleq:
- case Ogt:
- case Ogeq:
- if(!mathchk(n, 1)){
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = tint;
- break;
- case Oeq:
- case Oneq:
- switch(left->ty->kind){
- case Tint:
- case Tbig:
- case Tbyte:
- case Treal:
- case Tstring:
- case Tref:
- case Tlist:
- case Tarray:
- case Tchan:
- case Tany:
- case Tmodule:
- case Tfix:
- case Tpoly:
- if(!tcompat(left->ty, right->ty, 0) && !tcompat(right->ty, left->ty, 0))
- break;
- t = left->ty;
- if(t == tany)
- t = right->ty;
- if(t == tany)
- t = tint;
- if(left->ty == tany)
- left->ty = t;
- if(right->ty == tany)
- right->ty = t;
- n->ty = tint;
- return ok;
- }
- nerror(n, "cannot compare %Q to %Q", left, right);
- usedty(n->ty);
- ok.ok = ok.allok = 0;
- return ok;
- case Otype:
- if(!typeok){
- nerror(n, "%Q is not a variable", n);
- ok.ok = ok.allok = 0;
- return ok;
- }
- n->ty = usetype(n->ty);
- break;
- default:
- fatal("unknown op in typecheck: %O", n->op);
- }
- usedty(n->ty);
- return ok;
- }
- /*
- * n is syntactically a call, but n->left is not a fn
- * check if it's the contructor for an adt
- */
- Ok
- callcast(Node *n, int kidsok, int allok)
- {
- Node *left, *right;
- Decl *id;
- Type *t, *tt;
- Ok ok;
- left = n->left;
- right = n->right;
- id = nil;
- switch(left->op){
- case Oname:
- id = left->decl;
- break;
- case Omdot:
- if(left->right->op == Odot)
- id = left->right->right->decl;
- else
- id = left->right->decl;
- break;
- case Odot:
- id = left->right->decl;
- break;
- }
- /*
- (chan of int)(nil) looks awkward since both sets of brackets needed
- if(id == nil && right != nil && right->right == nil && (t = exptotype(left)) != nil){
- n->op = Ocast;
- n->left = right->left;
- n->right = nil;
- n->ty = t;
- return echeck(n, 0, 0, nil);
- }
- */
- if(id == nil || (id->store != Dtype && id->store != Dtag && id->ty->kind != Texception)){
- nerror(left, "%V is not a function or type name", left);
- ok.ok = ok.allok = 0;
- return ok;
- }
- if(id->store == Dtag)
- return tagcast(n, left, right, id, kidsok, allok);
- t = left->ty;
- n->ty = t;
- if(!kidsok){
- ok.ok = 1;
- ok.allok = 0;
- return ok;
- }
- if(t->kind == Tref)
- t = t->tof;
- tt = mktype(&n->src.start, &n->src.stop, Ttuple, nil, tuplefields(right));
- if(t->kind == Tadt && tcompat(t, tt, 1)){
- if(right == nil)
- *n = *n->left;
- ok.ok = 1;
- ok.allok = allok;
- return ok;
- }
- /* try an exception with args */
- tt = mktype(&n->src.start, &n->src.stop, Texception, nil, tuplefields(right));
- tt->cons = 1;
- if(t->kind == Texception && t->cons && tcompat(t, tt, 1)){
- if(right == nil)
- *n = *n->left;
- ok.ok = 1;
- ok.allok = allok;
- return ok;
- }
- /* try a cast */
- if(t->kind != Texception && right != nil && right->right == nil){ /* Oseq but single expression */
- right = right->left;
- n->op = Ocast;
- n->left = right;
- n->right = nil;
- n->ty = mkidtype(&n->src, id->sym);
- return echeck(n, 0, 0, nil);
- }
- nerror(left, "cannot make a %V from '(%v)'", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- Ok
- tagcast(Node *n, Node *left, Node *right, Decl *id, int kidsok, int allok)
- {
- Type *tt;
- Ok ok;
- left->ty = id->ty;
- if(left->op == Omdot)
- left->right->ty = id->ty;
- n->ty = id->ty;
- if(!kidsok){
- ok.ok = 1;
- ok.allok = 0;
- return ok;
- }
- id->ty->tof = usetype(id->ty->tof);
- if(right != nil)
- right->ty = id->ty->tof;
- tt = mktype(&n->src.start, &n->src.stop, Ttuple, nil, mkids(&nosrc, nil, tint, tuplefields(right)));
- tt->ids->store = Dfield;
- if(tcompat(id->ty->tof, tt, 1)){
- ok.ok = 1;
- ok.allok = allok;
- return ok;
- }
- nerror(left, "cannot make a %V from '(%v)'", left, right);
- ok.ok = ok.allok = 0;
- return ok;
- }
- int
- valistype(Node *n)
- {
- switch(n->op){
- case Oname:
- if(n->decl->store == Dtype)
- return 1;
- break;
- case Omdot:
- return valistype(n->right);
- }
- return 0;
- }
- int
- islval(Node *n)
- {
- int s;
- s = marklval(n);
- if(s == 1)
- return 1;
- if(s == 0)
- nerror(n, "cannot assign to %V", n);
- else
- circlval(n, n);
- return 0;
- }
- /*
- * check to see if n is an lval
- * mark the lval name as set
- */
- int
- marklval(Node *n)
- {
- Decl *id;
- Node *nn;
- int s;
- if(n == nil)
- return 0;
- switch(n->op){
- case Oname:
- return storespace[n->decl->store] && n->ty->kind != Texception; /*ZZZZ && n->decl->tagged == nil;*/
- case Odot:
- if(n->right->decl->store != Dfield)
- return 0;
- if(n->right->decl->cycle && !n->right->decl->cyc)
- return -1;
- if(n->left->ty->kind != Tref && marklval(n->left) == 0)
- nwarn(n, "assignment to %Q ignored", n);
- return 1;
- case Omdot:
- if(n->right->decl->store == Dglobal)
- return 1;
- return 0;
- case Oind:
- for(id = n->ty->ids; id != nil; id = id->next)
- if(id->cycle && !id->cyc)
- return -1;
- return 1;
- case Oslice:
- if(n->right->right->op != Onothing || n->ty == tstring)
- return 0;
- return 1;
- case Oinds:
- /*
- * make sure we don't change a string constant
- */
- switch(n->left->op){
- case Oconst:
- return 0;
- case Oname:
- return storespace[n->left->decl->store];
- case Odot:
- case Omdot:
- if(n->left->right->decl != nil)
- return storespace[n->left->right->decl->store];
- break;
- }
- return 1;
- case Oindex:
- case Oindx:
- return 1;
- case Otuple:
- for(nn = n->left; nn != nil; nn = nn->right){
- s = marklval(nn->left);
- if(s != 1)
- return s;
- }
- return 1;
- default:
- return 0;
- }
- }
- /*
- * n has a circular field assignment.
- * find it and print an error message.
- */
- int
- circlval(Node *n, Node *lval)
- {
- Decl *id;
- Node *nn;
- int s;
- if(n == nil)
- return 0;
- switch(n->op){
- case Oname:
- break;
- case Odot:
- if(oldcycles && n->right->decl->cycle && !n->right->decl->cyc){
- nerror(lval, "cannot assign to %V because field '%s' of %V could complete a cycle to %V",
- lval, n->right->decl->sym->name, n->left, n->left);
- return -1;
- }
- return 1;
- case Oind:
- if(!oldcycles)
- return 1;
- for(id = n->ty->ids; id != nil; id = id->next){
- if(id->cycle && !id->cyc){
- nerror(lval, "cannot assign to %V because field '%s' of %V could complete a cycle to %V",
- lval, id->sym->name, n, n);
- return -1;
- }
- }
- return 1;
- case Oslice:
- if(n->right->right->op != Onothing || n->ty == tstring)
- return 0;
- return 1;
- case Oindex:
- case Oinds:
- case Oindx:
- return 1;
- case Otuple:
- for(nn = n->left; nn != nil; nn = nn->right){
- s = circlval(nn->left, lval);
- if(s != 1)
- return s;
- }
- return 1;
- default:
- return 0;
- }
- return 0;
- }
- int
- mathchk(Node *n, int realok)
- {
- Type *tr, *tl;
- tl = n->left->ty;
- tr = n->right->ty;
- if(tr != tl && !tequal(tl, tr)){
- nerror(n, "type clash in %Q %O %Q", n->left, n->op, n->right);
- return 0;
- }
- n->ty = tr;
- switch(tr->kind){
- case Tint:
- case Tbig:
- case Tbyte:
- return 1;
- case Tstring:
- switch(n->op){
- case Oadd:
- case Oaddas:
- case Ogt:
- case Ogeq:
- case Olt:
- case Oleq:
- return 1;
- }
- break;
- case Treal:
- case Tfix:
- if(realok)
- return 1;
- break;
- }
- nerror(n, "cannot %O %Q and %Q", n->op, n->left, n->right);
- return 0;
- }
- int
- shiftchk(Node *n)
- {
- Node *left, *right;
- right = n->right;
- left = n->left;
- n->ty = left->ty;
- switch(n->ty->kind){
- case Tint:
- case Tbyte:
- case Tbig:
- if(right->ty->kind != Tint){
- nerror(n, "shift %Q is not an int", right);
- return 0;
- }
- return 1;
- }
- nerror(n, "cannot %Q %O %Q", left, n->op, right);
- return 0;
- }
- /*
- * check for any tany's in t
- */
- int
- specific(Type *t)
- {
- Decl *d;
- if(t == nil)
- return 0;
- switch(t->kind){
- case Terror:
- case Tnone:
- case Tint:
- case Tbig:
- case Tstring:
- case Tbyte:
- case Treal:
- case Tfn:
- case Tadt:
- case Tadtpick:
- case Tmodule:
- case Tfix:
- return 1;
- case Tany:
- return 0;
- case Tpoly:
- return 1;
- case Tref:
- case Tlist:
- case Tarray:
- case Tchan:
- return specific(t->tof);
- case Ttuple:
- case Texception:
- for(d = t->ids; d != nil; d = d->next)
- if(!specific(d->ty))
- return 0;
- return 1;
- }
- fatal("unknown type %T in specific", t);
- return 0;
- }
- /*
- * infer the type of all variable in n from t
- * n is the left-hand exp of a := exp
- */
- int
- declasinfer(Node *n, Type *t)
- {
- Decl *ids;
- int ok;
- if(t->kind == Texception){
- if(t->cons)
- return 0;
- t = mkextuptype(t);
- }
- switch(n->op){
- case Otuple:
- if(t->kind != Ttuple && t->kind != Tadt && t->kind != Tadtpick)
- return 0;
- ok = 1;
- n->ty = t;
- n = n->left;
- ids = t->ids;
- if(t->kind == Tadtpick)
- ids = t->tof->ids->next;
- for(; n != nil && ids != nil; ids = ids->next){
- if(ids->store != Dfield)
- continue;
- ok &= declasinfer(n->left, ids->ty);
- n = n->right;
- }
- for(; ids != nil; ids = ids->next)
- if(ids->store == Dfield)
- break;
- if(n != nil || ids != nil)
- return 0;
- return ok;
- case Oname:
- topvartype(t, n->decl, 0, 0);
- if(n->decl == nildecl)
- return 1;
- n->decl->ty = t;
- n->ty = t;
- shareloc(n->decl);
- return 1;
- }
- fatal("unknown op %n in declasinfer", n);
- return 0;
- }
- /*
- * an error occured in declaring n;
- * set all decl identifiers to Dwundef
- * so further errors are squashed.
- */
- void
- declaserr(Node *n)
- {
- switch(n->op){
- case Otuple:
- for(n = n->left; n != nil; n = n->right)
- declaserr(n->left);
- return;
- case Oname:
- if(n->decl != nildecl)
- n->decl->store = Dwundef;
- return;
- }
- fatal("unknown op %n in declaserr", n);
- }
- int
- argcompat(Node *n, Decl *f, Node *a)
- {
- for(; a != nil; a = a->right){
- if(f == nil){
- nerror(n, "%V: too many function arguments", n->left);
- return 0;
- }
- if(!tcompat(f->ty, a->left->ty, 0)){
- nerror(n, "%V: argument type mismatch: expected %T saw %Q",
- n->left, f->ty, a->left);
- return 0;
- }
- if(a->left->ty == tany)
- a->left->ty = f->ty;
- f = f->next;
- }
- if(f != nil){
- nerror(n, "%V: too few function arguments", n->left);
- return 0;
- }
- return 1;
- }
- /*
- * fn is Odot(adt, methid)
- * pass adt implicitly if needed
- * if not, any side effect of adt will be ignored
- */
- Node*
- passimplicit(Node *fn, Node *args)
- {
- Node *n;
- Type *t;
- t = fn->ty;
- n = fn->left;
- if(t->ids == nil || !t->ids->implicit){
- if(!isfnrefty(t) && hasside(n, 1))
- nwarn(fn, "result of expression %V ignored", n);
- return args;
- }
- if(n->op == Oname && n->decl->store == Dtype){
- nerror(n, "%V is a type and cannot be a self argument", n);
- n = mkn(Onothing, nil, nil);
- n->src = fn->src;
- n->ty = t->ids->ty;
- }
- args = mkn(Oseq, n, args);
- args->src = n->src;
- return args;
- }
- static int
- mem(Type *t, Decl *d)
- {
- for( ; d != nil; d = d->next)
- if(d->ty == t) /* was if(d->ty == t || tequal(d->ty, t)) */
- return 1;
- return 0;
- }
- static int
- memp(Type *t, Decl *f)
- {
- return mem(t, f->ty->polys) || mem(t, encpolys(f));
- }
- static void
- passfns0(Src *src, Decl *fn, Node *args0, Node **args, Node **a, Tpair *tp, Decl *polys)
- {
- Decl *id, *idt, *idf, *dot;
- Type *tt;
- Sym *sym;
- Node *n, *na, *mod;
- Tpair *p;
- if(debug['w']){
- print("polys: ");
- for(id=polys; id!=nil; id=id->next) print("%s ", id->sym->name);
- print("\nmap: ");
- for(p=tp; p!=nil; p=p->nxt) print("%T -> %T ", p->t1, p->t2);
- print("\n");
- }
- for(idt = polys; idt != nil; idt = idt->next){
- tt = valtmap(idt->ty, tp);
- if(tt->kind == Tpoly && fndec != nil && !memp(tt, fndec))
- error(src->start, "cannot determine the instantiated type of %T", tt);
- for(idf = idt->ty->ids; idf != nil; idf = idf->next){
- sym = idf->sym;
- id = fnlookup(sym, tt, &mod);
- while(id != nil && id->link != nil)
- id = id->link;
- if(debug['v']) print("fnlookup: %p\n", id);
- if(id == nil) /* error flagged already */
- continue;
- id->refs++;
- id->caninline = -1;
- if(tt->kind == Tmodule){ /* mod an actual parameter */
- for(;;){
- if(args0 != nil && tequal(tt, args0->left->ty)){
- mod = args0->left;
- break;
- }
- if(args0 == nil)
- break;
- args0 = args0->right;
- }
- }
- if(mod == nil && (dot = module(id)) != nil && !isimpmod(dot->sym))
- error(src->start, "cannot use %s without importing %s from a variable", id->sym->name, id->dot->sym->name);
- if(debug['U']) print("fp: %s %s %s\n", fn->sym->name, mod ? mod->decl->sym->name : "nil", id->sym->name);
- n = mkn(Ofnptr, mod, mkdeclname(src, id));
- n->src = *src;
- n->decl = fn;
- if(tt->kind == Tpoly)
- n->flags = FNPTRA;
- else
- n->flags = 0;
- na = mkn(Oseq, n, nil);
- if(*a == nil)
- *args = na;
- else
- (*a)->right = na;
-
- n = mkn(Ofnptr, mod, mkdeclname(src, id));
- n->src = *src;
- n->decl = fn;
- if(tt->kind == Tpoly)
- n->flags = FNPTRA|FNPTR2;
- else
- n->flags = FNPTR2;
- *a = na->right = mkn(Oseq, n, nil);
- }
- if(args0 != nil)
- args0 = args0->right;
- }
- }
- Node*
- passfns(Src *src, Decl *fn, Node *left, Node *args, Type *adt, Tpair *tp)
- {
- Node *a, *args0;
- a = nil;
- args0 = args;
- if(args != nil)
- for(a = args; a->right != nil; a = a->right)
- ;
- passfns0(src, fn, args0, &args, &a, tp, ispoly(fn) ? fn->ty->polys : left->ty->tof->polys);
- if(adt != nil)
- passfns0(src, fn, args0, &args, &a, adt->u.tmap, ispoly(fn) ? encpolys(fn) : nil);
- return args;
- }
- /*
- * check the types for a function with a variable number of arguments
- * last typed argument must be a constant string, and must use the
- * print format for describing arguments.
- */
- Type*
- mkvarargs(Node *n, Node *args)
- {
- Node *s, *a;
- Decl *f, *last, *va;
- Type *nt;
- nt = copytypeids(n->ty);
- n->ty = nt;
- f = n->ty->ids;
- last = nil;
- if(f == nil){
- nerror(n, "%V's type is illegal", n);
- return nt;
- }
- s = args;
- for(a = args; a != nil; a = a->right){
- if(f == nil)
- break;
- if(!tcompat(f->ty, a->left->ty, 0)){
- nerror(n, "%V: argument type mismatch: expected %T saw %Q",
- n, f->ty, a->left);
- return nt;
- }
- if(a->left->ty == tany)
- a->left->ty = f->ty;
- last = f;
- f = f->next;
- s = a;
- }
- if(f != nil){
- nerror(n, "%V: too few function arguments", n);
- return nt;
- }
- s->left = fold(s->left);
- s = s->left;
- if(s->ty != tstring || s->op != Oconst){
- nerror(args, "%V: format argument %Q is not a string constant", n, s);
- return nt;
- }
- fmtcheck(n, s, a);
- va = tuplefields(a);
- if(last == nil)
- nt->ids = va;
- else
- last->next = va;
- return nt;
- }
- /*
- * check that a print style format string matches its arguments
- */
- void
- fmtcheck(Node *f, Node *fmtarg, Node *va)
- {
- Sym *fmt;
- Rune r;
- char *s, flags[10];
- int i, c, n1, n2, dot, verb, flag, ns, lens, fmtstart;
- Type *ty;
- fmt = fmtarg->decl->sym;
- s = fmt->name;
- lens = fmt->len;
- ns = 0;
- while(ns < lens){
- c = s[ns++];
- if(c != '%')
- continue;
- verb = -1;
- n1 = 0;
- n2 = 0;
- dot = 0;
- flag = 0;
- fmtstart = ns - 1;
- while(ns < lens && verb < 0){
- c = s[ns++];
- switch(c){
- default:
- chartorune(&r, &s[ns-1]);
- nerror(f, "%V: invalid character %C in format '%.*s'", f, r, ns-fmtstart, &s[fmtstart]);
- return;
- case '.':
- if(dot){
- nerror(f, "%V: invalid format '%.*s'", f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- n1 = 1;
- dot = 1;
- continue;
- case '*':
- if(!n1)
- n1 = 1;
- else if(!n2 && dot)
- n2 = 1;
- else{
- nerror(f, "%V: invalid format '%.*s'", f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- if(va == nil){
- nerror(f, "%V: too few arguments for format '%.*s'",
- f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- if(va->left->ty->kind != Tint){
- nerror(f, "%V: format '%.*s' incompatible with argument %Q",
- f, ns-fmtstart, &s[fmtstart], va->left);
- return;
- }
- va = va->right;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- while(ns < lens && s[ns] >= '0' && s[ns] <= '9')
- ns++;
- if(!n1)
- n1 = 1;
- else if(!n2 && dot)
- n2 = 1;
- else{
- nerror(f, "%V: invalid format '%.*s'", f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- break;
- case '+':
- case '-':
- case '#':
- case ',':
- case 'b':
- case 'u':
- for(i = 0; i < flag; i++){
- if(flags[i] == c){
- nerror(f, "%V: duplicate flag %c in format '%.*s'",
- f, c, ns-fmtstart, &s[fmtstart]);
- return;
- }
- }
- flags[flag++] = c;
- if(flag >= sizeof flags){
- nerror(f, "too many flags in format '%.*s'", ns-fmtstart, &s[fmtstart]);
- return;
- }
- break;
- case '%':
- case 'r':
- verb = Tnone;
- break;
- case 'H':
- verb = Tany;
- break;
- case 'c':
- verb = Tint;
- break;
- case 'd':
- case 'o':
- case 'x':
- case 'X':
- verb = Tint;
- for(i = 0; i < flag; i++){
- if(flags[i] == 'b'){
- verb = Tbig;
- break;
- }
- }
- break;
- case 'e':
- case 'f':
- case 'g':
- case 'E':
- case 'G':
- verb = Treal;
- break;
- case 's':
- case 'q':
- verb = Tstring;
- break;
- }
- }
- if(verb != Tnone){
- if(verb < 0){
- nerror(f, "%V: incomplete format '%.*s'", f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- if(va == nil){
- nerror(f, "%V: too few arguments for format '%.*s'", f, ns-fmtstart, &s[fmtstart]);
- return;
- }
- ty = va->left->ty;
- if(ty->kind == Texception)
- ty = mkextuptype(ty);
- switch(verb){
- case Tint:
- switch(ty->kind){
- case Tstring:
- case Tarray:
- case Tref:
- case Tchan:
- case Tlist:
- case Tmodule:
- if(c == 'x' || c == 'X')
- verb = ty->kind;
- break;
- }
- break;
- case Tany:
- if(tattr[ty->kind].isptr)
- verb = ty->kind;
- break;
- }
- if(verb != ty->kind){
- nerror(f, "%V: format '%.*s' incompatible with argument %Q", f, ns-fmtstart, &s[fmtstart], va->left);
- return;
- }
- va = va->right;
- }
- }
- if(va != nil)
- nerror(f, "%V: more arguments than formats", f);
- }
- Decl*
- tuplefields(Node *n)
- {
- Decl *d, *h, **last;
- h = nil;
- last = &h;
- for(; n != nil; n = n->right){
- d = mkdecl(&n->left->src, Dfield, n->left->ty);
- *last = d;
- last = &d->next;
- }
- return h;
- }
- /*
- * make explicit indices for every element in an array initializer
- * return the maximum index
- * sort the indices and check for duplicates
- */
- int
- assignindices(Node *ar)
- {
- Node *wild, *off, *size, *inits, *n, *q;
- Type *t;
- Case *c;
- int amax, max, last, nlab, ok;
- amax = 0x7fffffff;
- size = dupn(0, &nosrc, ar->left);
- if(size->ty == tint){
- size = fold(size);
- if(size->op == Oconst)
- amax = size->val;
- }
- inits = ar->right;
- max = -1;
- last = -1;
- t = inits->left->ty;
- wild = nil;
- nlab = 0;
- ok = 1;
- for(n = inits; n != nil; n = n->right){
- if(!tcompat(t, n->left->ty, 0)){
- t = tparent(t, n->left->ty);
- if(!tcompat(t, n->left->ty, 0)){
- nerror(n->left, "inconsistent types %T and %T and in array initializer", t, n->left->ty);
- return -1;
- }
- else
- inits->left->ty = t;
- }
- if(t == tany)
- t = n->left->ty;
- /*
- * make up an index if there isn't one
- */
- if(n->left->left == nil)
- n->left->left = mkn(Oseq, mkconst(&n->left->right->src, last + 1), nil);
- for(q = n->left->left; q != nil; q = q->right){
- off = q->left;
- if(off->ty != tint){
- nerror(off, "array index %Q is not an int", off);
- ok = 0;
- continue;
- }
- off = fold(off);
- switch(off->op){
- case Owild:
- if(wild != nil)
- nerror(off, "array index * duplicated on line %L", wild->src.start);
- wild = off;
- continue;
- case Orange:
- if(off->left->op != Oconst || off->right->op != Oconst){
- nerror(off, "range %V is not constant", off);
- off = nil;
- }else if(off->left->val < 0 || off->right->val >= amax){
- nerror(off, "array index %V out of bounds", off);
- off = nil;
- }else
- last = off->right->val;
- break;
- case Oconst:
- last = off->val;
- if(off->val < 0 || off->val >= amax){
- nerror(off, "array index %V out of bounds", off);
- off = nil;
- }
- break;
- case Onothing:
- /* get here from a syntax error */
- off = nil;
- break;
- default:
- nerror(off, "array index %V is not constant", off);
- off = nil;
- break;
- }
- nlab++;
- if(off == nil){
- off = mkconst(&n->left->right->src, last);
- ok = 0;
- }
- if(last > max)
- max = last;
- q->left = off;
- }
- }
- /*
- * fix up types of nil elements
- */
- for(n = inits; n != nil; n = n->right)
- if(n->left->ty == tany)
- n->left->ty = t;
- if(!ok)
- return -1;
- c = checklabels(inits, tint, nlab, "array index");
- t = mktype(&inits->src.start, &inits->src.stop, Tainit, nil, nil);
- inits->ty = t;
- t->cse = c;
- return max + 1;
- }
- /*
- * check the labels of a case statment
- */
- void
- casecheck(Node *cn, Type *ret)
- {
- Node *n, *q, *wild, *left, *arg;
- Type *t;
- Case *c;
- Ok rok;
- int nlab, ok, op;
- rok = echeck(cn->left, 0, 0, nil);
- cn->right = scheck(cn->right, ret, Sother);
- if(!rok.ok)
- return;
- arg = cn->left;
- t = arg->ty;
- if(t != tint && t != tbig && t != tstring){
- nerror(cn, "case argument %Q is not an int or big or string", arg);
- return;
- }
- wild = nil;
- nlab= 0;
- ok = 1;
- for(n = cn->right; n != nil; n = n->right){
- q = n->left->left;
- if(n->left->right->right == nil)
- nwarn(q, "no body for case qualifier %V", q);
- for(; q != nil; q = q->right){
- left = fold(q->left);
- q->left = left;
- switch(left->op){
- case Owild:
- if(wild != nil)
- nerror(left, "case qualifier * duplicated on line %L", wild->src.start);
- wild = left;
- break;
- case Orange:
- if(left->ty != t)
- nerror(left, "case qualifier %Q clashes with %Q", left, arg);
- else if(left->left->op != Oconst || left->right->op != Oconst){
- nerror(left, "case range %V is not constant", left);
- ok = 0;
- }
- nlab++;
- break;
- default:
- if(left->ty != t){
- nerror(left, "case qualifier %Q clashes with %Q", left, arg);
- ok = 0;
- }else if(left->op != Oconst){
- nerror(left, "case qualifier %V is not constant", left);
- ok = 0;
- }
- nlab++;
- break;
- }
- }
- }
- if(!ok)
- return;
- c = checklabels(cn->right, t, nlab, "case qualifier");
- op = Tcase;
- if(t == tbig)
- op = Tcasel;
- else if(t == tstring)
- op = Tcasec;
- t = mktype(&cn->src.start, &cn->src.stop, op, nil, nil);
- cn->ty = t;
- t->cse = c;
- }
- /*
- * check the labels and bodies of a pick statment
- */
- void
- pickcheck(Node *n, Type *ret)
- {
- Node *w, *arg, *qs, *q, *qt, *left, **tags;
- Decl *id, *d;
- Type *t, *argty;
- Case *c;
- Ok rok;
- int ok, nlab;
- arg = n->left->right;
- rok = echeck(arg, 0, 0, nil);
- if(!rok.allok)
- return;
- t = arg->ty;
- if(t->kind == Tref)
- t = t->tof;
- if(arg->ty->kind != Tref || t->kind != Tadt || t->tags == nil){
- nerror(arg, "pick argument %Q is not a ref adt with pick tags", arg);
- return;
- }
- argty = usetype(mktype(&arg->ty->src.start, &arg->ty->src.stop, Tref, t, nil));
- arg = n->left->left;
- pushscope(nil, Sother);
- dasdecl(arg);
- arg->decl->ty = argty;
- arg->ty = argty;
- tags = allocmem(t->decl->tag * sizeof *tags);
- memset(tags, 0, t->decl->tag * sizeof *tags);
- w = nil;
- ok = 1;
- nlab = 0;
- for(qs = n->right; qs != nil; qs = qs->right){
- qt = nil;
- for(q = qs->left->left; q != nil; q = q->right){
- left = q->left;
- switch(left->op){
- case Owild:
- /* left->ty = tnone; */
- left->ty = t;
- if(w != nil)
- nerror(left, "pick qualifier * duplicated on line %L", w->src.start);
- w = left;
- break;
- case Oname:
- id = namedot(t->tags, left->decl->sym);
- if(id == nil){
- nerror(left, "pick qualifier %V is not a member of %Q", left, arg);
- ok = 0;
- continue;
- }
- left->decl = id;
- left->ty = id->ty;
- if(tags[id->tag] != nil){
- nerror(left, "pick qualifier %V duplicated on line %L",
- left, tags[id->tag]->src.start);
- ok = 0;
- }
- tags[id->tag] = left;
- nlab++;
- break;
- default:
- fatal("pickcheck can't handle %n", q);
- break;
- }
- if(qt == nil)
- qt = left;
- else if(!tequal(qt->ty, left->ty))
- nerror(left, "type clash in pick qualifiers %Q and %Q", qt, left);
- }
- argty->tof = t;
- if(qt != nil)
- argty->tof = qt->ty;
- qs->left->right = scheck(qs->left->right, ret, Sother);
- if(qs->left->right == nil)
- nwarn(qs->left->left, "no body for pick qualifier %V", qs->left->left);
- }
- argty->tof = t;
- for(qs = n->right; qs != nil; qs = qs->right)
- for(q = qs->left->left; q != nil; q = q->right)
- q->left = fold(q->left);
- d = popscope();
- d->refs++;
- if(d->next != nil)
- fatal("pickcheck: installing more than one id");
- fndecls = appdecls(fndecls, d);
- if(!ok)
- return;
- c = checklabels(n->right, tint, nlab, "pick qualifier");
- t = mktype(&n->src.start, &n->src.stop, Tcase, nil, nil);
- n->ty = t;
- t->cse = c;
- }
- void
- exccheck(Node *en, Type *ret)
- {
- Decl *ed;
- Node *n, *q, *wild, *left, *oinexcept;
- Type *t, *qt;
- Case *c;
- int nlab, ok;
- Ok rok;
- char buf[32];
- static int nexc;
- pushscope(nil, Sother);
- if(en->left == nil){
- seprint(buf, buf+sizeof(buf), ".ex%d", nexc++);
- en->left = mkdeclname(&en->src, mkids(&en->src, enter(buf, 0), texception, nil));
- }
- oinexcept = inexcept;
- inexcept = en->left;
- dasdecl(en->left);
- en->left->ty = en->left->decl->ty = texception;
- ed = en->left->decl;
- /* en->right = scheck(en->right, ret, Sother); */
- t = tstring;
- wild = nil;
- nlab = 0;
- ok = 1;
- for(n = en->right; n != nil; n = n->right){
- qt = nil;
- for(q = n->left->left; q != nil; q = q->right){
- left = q->left;
- switch(left->op){
- case Owild:
- left->ty = texception;
- if(wild != nil)
- nerror(left, "exception qualifier * duplicated on line %L", wild->src.start);
- wild = left;
- break;
- case Orange:
- left->ty = tnone;
- nerror(left, "exception qualifier %V is illegal", left);
- ok = 0;
- break;
- default:
- rok = echeck(left, 0, 0, nil);
- if(!rok.ok){
- ok = 0;
- break;
- }
- left = q->left = fold(left);
- if(left->ty != t && left->ty->kind != Texception){
- nerror(left, "exception qualifier %Q is not a string or exception", left);
- ok = 0;
- }else if(left->op != Oconst){
- nerror(left, "exception qualifier %V is not constant", left);
- ok = 0;
- }
- else if(left->ty != t)
- left->ty = mkextype(left->ty);
- nlab++;
- break;
- }
- if(qt == nil)
- qt = left->ty;
- else if(!tequal(qt, left->ty))
- qt = texception;
- }
- if(qt != nil)
- ed->ty = qt;
- n->left->right = scheck(n->left->right, ret, Sother);
- if(n->left->right->right == nil)
- nwarn(n->left->left, "no body for exception qualifier %V", n->left->left);
- }
- ed->ty = texception;
- inexcept = oinexcept;
- if(!ok)
- return;
- c = checklabels(en->right, texception, nlab, "exception qualifier");
- t = mktype(&en->src.start, &en->src.stop, Texcept, nil, nil);
- en->ty = t;
- t->cse = c;
- ed = popscope();
- fndecls = appdecls(fndecls, ed);
- }
- /*
- * check array and case labels for validity
- */
- Case *
- checklabels(Node *inits, Type *ctype, int nlab, char *title)
- {
- Node *n, *p, *q, *wild;
- Label *labs, *aux;
- Case *c;
- char buf[256], buf1[256];
- int i, e;
- labs = allocmem(nlab * sizeof *labs);
- i = 0;
- wild = nil;
- for(n = inits; n != nil; n = n->right){
- for(q = n->left->left; q != nil; q = q->right){
- switch(q->left->op){
- case Oconst:
- labs[i].start = q->left;
- labs[i].stop = q->left;
- labs[i++].node = n->left;
- break;
- case Orange:
- labs[i].start = q->left->left;
- labs[i].stop = q->left->right;
- labs[i++].node = n->left;
- break;
- case Owild:
- wild = n->left;
- break;
- default:
- fatal("bogus index in checklabels");
- break;
- }
- }
- }
- if(i != nlab)
- fatal("bad label count: %d then %d", nlab, i);
- aux = allocmem(nlab * sizeof *aux);
- casesort(ctype, aux, labs, 0, nlab);
- for(i = 0; i < nlab; i++){
- p = labs[i].stop;
- if(casecmp(ctype, labs[i].start, p) > 0)
- nerror(labs[i].start, "unmatchable %s %V", title, labs[i].node);
- for(e = i + 1; e < nlab; e++){
- if(casecmp(ctype, labs[e].start, p) <= 0){
- eprintlist(buf, buf+sizeof(buf), labs[e].node->left, " or ");
- eprintlist(buf1, buf1+sizeof(buf1), labs[e-1].node->left, " or ");
- nerror(labs[e].start,"%s '%s' overlaps with '%s' on line %L",
- title, buf, buf1, p->src.start);
- }
- /*
- * check for merging case labels
- */
- if(ctype != tint
- || labs[e].start->val != p->val+1
- || labs[e].node != labs[i].node)
- break;
- p = labs[e].stop;
- }
- if(e != i + 1){
- labs[i].stop = p;
- memmove(&labs[i+1], &labs[e], (nlab-e) * sizeof *labs);
- nlab -= e - (i + 1);
- }
- }
- free(aux);
- c = allocmem(sizeof *c);
- c->nlab = nlab;
- c->nsnd = 0;
- c->labs = labs;
- c->wild = wild;
- return c;
- }
- static int
- matchcmp(Node *na, Node *nb)
- {
- Sym *a, *b;
- int sa, sb;
- a = na->decl->sym;
- b = nb->decl->sym;
- sa = a->len > 0 && a->name[a->len-1] == '*';
- sb = b->len > 0 && b->name[b->len-1] == '*';
- if(sa){
- if(sb){
- if(a->len == b->len)
- return symcmp(a, b);
- return b->len-a->len;
- }
- else
- return 1;
- }
- else{
- if(sb)
- return -1;
- else{
- if(na->ty == tstring){
- if(nb->ty == tstring)
- return symcmp(a, b);
- else
- return 1;
- }
- else{
- if(nb->ty == tstring)
- return -1;
- else
- return symcmp(a, b);
- }
- }
- }
- }
- int
- casecmp(Type *ty, Node *a, Node *b)
- {
- if(ty == tint || ty == tbig){
- if(a->val < b->val)
- return -1;
- if(a->val > b->val)
- return 1;
- return 0;
- }
- if(ty == texception)
- return matchcmp(a, b);
- return symcmp(a->decl->sym, b->decl->sym);
- }
- void
- casesort(Type *t, Label *aux, Label *labs, int start, int stop)
- {
- int n, top, mid, base;
- n = stop - start;
- if(n <= 1)
- return;
- top = mid = start + n / 2;
- casesort(t, aux, labs, start, top);
- casesort(t, aux, labs, mid, stop);
- /*
- * merge together two sorted label arrays, yielding a sorted array
- */
- n = 0;
- base = start;
- while(base < top && mid < stop){
- if(casecmp(t, labs[base].start, labs[mid].start) <= 0)
- aux[n++] = labs[base++];
- else
- aux[n++] = labs[mid++];
- }
- if(base < top)
- memmove(&aux[n], &labs[base], (top-base) * sizeof *aux);
- else if(mid < stop)
- memmove(&aux[n], &labs[mid], (stop-mid) * sizeof *aux);
- memmove(&labs[start], &aux[0], (stop-start) * sizeof *labs);
- }
- /*
- * binary search for the label corresponding to a given value
- */
- int
- findlab(Type *ty, Node *v, Label *labs, int nlab)
- {
- int l, r, m;
- if(nlab <= 1)
- return 0;
- l = 1;
- r = nlab - 1;
- while(l <= r){
- m = (r + l) / 2;
- if(casecmp(ty, labs[m].start, v) <= 0)
- l = m + 1;
- else
- r = m - 1;
- }
- m = l - 1;
- if(casecmp(ty, labs[m].start, v) > 0
- || casecmp(ty, labs[m].stop, v) < 0)
- fatal("findlab out of range");
- return m;
- }
- void
- altcheck(Node *an, Type *ret)
- {
- Node *n, *q, *left, *op, *wild;
- Case *c;
- int ok, nsnd, nrcv;
- an->left = scheck(an->left, ret, Sother);
- ok = 1;
- nsnd = 0;
- nrcv = 0;
- wild = nil;
- for(n = an->left; n != nil; n = n->right){
- q = n->left->right->left;
- if(n->left->right->right == nil)
- nwarn(q, "no body for alt guard %V", q);
- for(; q != nil; q = q->right){
- left = q->left;
- switch(left->op){
- case Owild:
- if(wild != nil)
- nerror(left, "alt guard * duplicated on line %L", wild->src.start);
- wild = left;
- break;
- case Orange:
- nerror(left, "alt guard %V is illegal", left);
- ok = 0;
- break;
- default:
- op = hascomm(left);
- if(op == nil){
- nerror(left, "alt guard %V has no communication", left);
- ok = 0;
- break;
- }
- if(op->op == Osnd)
- nsnd++;
- else
- nrcv++;
- break;
- }
- }
- }
- if(!ok)
- return;
- c = allocmem(sizeof *c);
- c->nlab = nsnd + nrcv;
- c->nsnd = nsnd;
- c->wild = wild;
- an->ty = mktalt(c);
- }
- Node*
- hascomm(Node *n)
- {
- Node *r;
- if(n == nil)
- return nil;
- if(n->op == Osnd || n->op == Orcv)
- return n;
- r = hascomm(n->left);
- if(r != nil)
- return r;
- return hascomm(n->right);
- }
- void
- raisescheck(Type *t)
- {
- Node *n, *nn;
- Ok ok;
- if(t->kind != Tfn)
- return;
- n = t->u.eraises;
- for(nn = n->left; nn != nil; nn = nn->right){
- ok = echeck(nn->left, 0, 0, nil);
- if(ok.ok && nn->left->ty->kind != Texception)
- nerror(n, "%V: illegal raises expression", nn->left);
- }
- }
- typedef struct Elist Elist;
- struct Elist{
- Decl *d;
- Elist *nxt;
- };
- static Elist*
- emerge(Elist *el1, Elist *el2)
- {
- int f;
- Elist *el, *nxt;
- for( ; el1 != nil; el1 = nxt){
- f = 0;
- for(el = el2; el != nil; el = el->nxt){
- if(el1->d == el->d){
- f = 1;
- break;
- }
- }
- nxt = el1->nxt;
- if(!f){
- el1->nxt = el2;
- el2 = el1;
- }
- }
- return el2;
- }
- static Elist*
- equals(Node *n)
- {
- Node *q, *nn;
- Elist *e, *el;
- el = nil;
- for(q = n->left->left; q != nil; q = q->right){
- nn = q->left;
- if(nn->op == Owild)
- return nil;
- if(nn->ty->kind != Texception)
- continue;
- e = (Elist*)malloc(sizeof(Elist));
- e->d = nn->decl;
- e->nxt = el;
- el = e;
- }
- return el;
- }
- static int
- caught(Decl *d, Node *n)
- {
- Node *q, *nn;
- for(n = n->right; n != nil; n = n->right){
- for(q = n->left->left; q != nil; q = q->right){
- nn = q->left;
- if(nn->op == Owild)
- return 1;
- if(nn->ty->kind != Texception)
- continue;
- if(d == nn->decl)
- return 1;
- }
- }
- return 0;
- }
- static Elist*
- raisecheck(Node *n, Elist *ql)
- {
- int exc;
- Node *e;
- Elist *el, *nel, *nxt;
- if(n == nil)
- return nil;
- el = nil;
- for(; n != nil; n = n->right){
- switch(n->op){
- case Oscope:
- return raisecheck(n->right, ql);
- case Olabel:
- case Odo:
- return raisecheck(n->right, ql);
- case Oif:
- case Ofor:
- return emerge(raisecheck(n->right->left, ql),
- raisecheck(n->right->right, ql));
- case Oalt:
- case Ocase:
- case Opick:
- case Oexcept:
- exc = n->op == Oexcept;
- for(n = n->right; n != nil; n = n->right){
- ql = nil;
- if(exc)
- ql = equals(n);
- el = emerge(raisecheck(n->left->right, ql), el);
- }
- return el;
- case Oseq:
- el = emerge(raisecheck(n->left, ql), el);
- break;
- case Oexstmt:
- el = raisecheck(n->left, ql);
- nel = nil;
- for( ; el != nil; el = nxt){
- nxt = el->nxt;
- if(!caught(el->d, n->right)){
- el->nxt = nel;
- nel = el;
- }
- }
- return emerge(nel, raisecheck(n->right, ql));
- case Oraise:
- e = n->left;
- if(e->ty && e->ty->kind == Texception){
- if(!e->ty->cons)
- return ql;
- if(e->op == Ocall)
- e = e->left;
- if(e->op == Omdot)
- e = e->right;
- if(e->op != Oname)
- fatal("exception %n not a name", e);
- el = (Elist*)malloc(sizeof(Elist));
- el->d = e->decl;
- el->nxt = nil;
- return el;
- }
- return nil;
- default:
- return nil;
- }
- }
- return el;
- }
- void
- checkraises(Node *n)
- {
- int f;
- Decl *d;
- Elist *e, *el;
- Node *es, *nn;
- el = raisecheck(n->right, nil);
- es = n->ty->u.eraises;
- if(es != nil){
- for(nn = es->left; nn != nil; nn = nn->right){
- d = nn->left->decl;
- f = 0;
- for(e = el; e != nil; e = e->nxt){
- if(d == e->d){
- f = 1;
- e->d = nil;
- break;
- }
- }
- if(!f)
- nwarn(n, "function %V does not raise %s but declared", n->left, d->sym->name);
- }
- }
- for(e = el; e != nil; e = e->nxt)
- if(e->d != nil)
- nwarn(n, "function %V raises %s but not declared", n->left, e->d->sym->name);
- }
- /* sort all globals in modules now that we've finished with 'last' pointers
- * and before any code generation
- */
- void
- gsort(Node *n)
- {
- for(;;){
- if(n == nil)
- return;
- if(n->op != Oseq)
- break;
- gsort(n->left);
- n = n->right;
- }
- if(n->op == Omoddecl && n->ty->ok & OKverify){
- n->ty->ids = namesort(n->ty->ids);
- sizeids(n->ty->ids, 0);
- }
- }
|