1*0d13e2d8SCharles.Forsythimplement Calc; 2*0d13e2d8SCharles.Forsyth 3*0d13e2d8SCharles.Forsythinclude "sys.m"; 4*0d13e2d8SCharles.Forsyth sys: Sys; 5*0d13e2d8SCharles.Forsythinclude "draw.m"; 6*0d13e2d8SCharles.Forsythinclude "arg.m"; 7*0d13e2d8SCharles.Forsyth arg: Arg; 8*0d13e2d8SCharles.Forsythinclude "bufio.m"; 9*0d13e2d8SCharles.Forsyth bufio: Bufio; 10*0d13e2d8SCharles.Forsyth Iobuf: import bufio; 11*0d13e2d8SCharles.Forsythinclude "math.m"; 12*0d13e2d8SCharles.Forsyth maths: Math; 13*0d13e2d8SCharles.Forsythinclude "rand.m"; 14*0d13e2d8SCharles.Forsyth rand: Rand; 15*0d13e2d8SCharles.Forsythinclude "daytime.m"; 16*0d13e2d8SCharles.Forsyth daytime: Daytime; 17*0d13e2d8SCharles.Forsyth 18*0d13e2d8SCharles.ForsythCalc: module 19*0d13e2d8SCharles.Forsyth{ 20*0d13e2d8SCharles.Forsyth init: fn(nil: ref Draw->Context, argv: list of string); 21*0d13e2d8SCharles.Forsyth}; 22*0d13e2d8SCharles.Forsyth 23*0d13e2d8SCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 24*0d13e2d8SCharles.Forsyth{ 25*0d13e2d8SCharles.Forsyth sys = load Sys Sys->PATH; 26*0d13e2d8SCharles.Forsyth arg = load Arg Arg->PATH; 27*0d13e2d8SCharles.Forsyth bufio = load Bufio Bufio->PATH; 28*0d13e2d8SCharles.Forsyth maths = load Math Math->PATH; 29*0d13e2d8SCharles.Forsyth rand = load Rand Rand->PATH; 30*0d13e2d8SCharles.Forsyth daytime = load Daytime Daytime->PATH; 31*0d13e2d8SCharles.Forsyth 32*0d13e2d8SCharles.Forsyth maths->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); 33*0d13e2d8SCharles.Forsyth 34*0d13e2d8SCharles.Forsyth rand->init(daytime->now()); 35*0d13e2d8SCharles.Forsyth rand->init(rand->rand(Big)^rand->rand(Big)); 36*0d13e2d8SCharles.Forsyth daytime = nil; 37*0d13e2d8SCharles.Forsyth 38*0d13e2d8SCharles.Forsyth arg->init(args); 39*0d13e2d8SCharles.Forsyth while((c := arg->opt()) != 0){ 40*0d13e2d8SCharles.Forsyth case(c){ 41*0d13e2d8SCharles.Forsyth 'b' => 42*0d13e2d8SCharles.Forsyth bits = 1; 43*0d13e2d8SCharles.Forsyth 'd' => 44*0d13e2d8SCharles.Forsyth debug = 1; 45*0d13e2d8SCharles.Forsyth 's' => 46*0d13e2d8SCharles.Forsyth strict = 1; 47*0d13e2d8SCharles.Forsyth } 48*0d13e2d8SCharles.Forsyth } 49*0d13e2d8SCharles.Forsyth gargs = args = arg->argv(); 50*0d13e2d8SCharles.Forsyth if(args == nil){ 51*0d13e2d8SCharles.Forsyth stdin = 1; 52*0d13e2d8SCharles.Forsyth bin = bufio->fopen(sys->fildes(0), Sys->OREAD); 53*0d13e2d8SCharles.Forsyth } 54*0d13e2d8SCharles.Forsyth else if(tl args == nil) 55*0d13e2d8SCharles.Forsyth bin = bufio->open(hd args, Sys->OREAD); 56*0d13e2d8SCharles.Forsyth 57*0d13e2d8SCharles.Forsyth syms = array[Hash] of ref Sym; 58*0d13e2d8SCharles.Forsyth 59*0d13e2d8SCharles.Forsyth pushscope(); 60*0d13e2d8SCharles.Forsyth for(i := 0; keyw[i].t0 != nil; i++) 61*0d13e2d8SCharles.Forsyth enter(keyw[i].t0, keyw[i].t1); 62*0d13e2d8SCharles.Forsyth for(i = 0; conw[i].t0 != nil; i++) 63*0d13e2d8SCharles.Forsyth adddec(conw[i].t0, Ocon, conw[i].t1, 0); 64*0d13e2d8SCharles.Forsyth for(i = 0; varw[i].t0 != nil; i++) 65*0d13e2d8SCharles.Forsyth adddec(varw[i].t0, Ovar, varw[i].t1, 0); 66*0d13e2d8SCharles.Forsyth for(i = 0; funw[i].t0 != nil; i++) 67*0d13e2d8SCharles.Forsyth adddec(funw[i].t0, Olfun, real funw[i].t1, funw[i].t2); 68*0d13e2d8SCharles.Forsyth 69*0d13e2d8SCharles.Forsyth deg = lookup(Deg).dec; 70*0d13e2d8SCharles.Forsyth pbase = lookup(Base).dec; 71*0d13e2d8SCharles.Forsyth errdec = ref Dec; 72*0d13e2d8SCharles.Forsyth 73*0d13e2d8SCharles.Forsyth pushscope(); 74*0d13e2d8SCharles.Forsyth for(;;){ 75*0d13e2d8SCharles.Forsyth e: ref Node; 76*0d13e2d8SCharles.Forsyth 77*0d13e2d8SCharles.Forsyth { 78*0d13e2d8SCharles.Forsyth t := lex(); 79*0d13e2d8SCharles.Forsyth if(t == Oeof) 80*0d13e2d8SCharles.Forsyth break; 81*0d13e2d8SCharles.Forsyth unlex(t); 82*0d13e2d8SCharles.Forsyth ls := lexes; 83*0d13e2d8SCharles.Forsyth e = stat(1); 84*0d13e2d8SCharles.Forsyth ckstat(e, Onothing, 0); 85*0d13e2d8SCharles.Forsyth if(ls == lexes){ 86*0d13e2d8SCharles.Forsyth t = lex(); 87*0d13e2d8SCharles.Forsyth error(nil, sys->sprint("syntax error near %s", opstring(t))); 88*0d13e2d8SCharles.Forsyth unlex(t); 89*0d13e2d8SCharles.Forsyth } 90*0d13e2d8SCharles.Forsyth consume(Onl); 91*0d13e2d8SCharles.Forsyth } 92*0d13e2d8SCharles.Forsyth exception ex{ 93*0d13e2d8SCharles.Forsyth Eeof => 94*0d13e2d8SCharles.Forsyth e = nil; 95*0d13e2d8SCharles.Forsyth err("premature eof"); 96*0d13e2d8SCharles.Forsyth skip(); 97*0d13e2d8SCharles.Forsyth "*" => 98*0d13e2d8SCharles.Forsyth e = nil; 99*0d13e2d8SCharles.Forsyth err(ex); 100*0d13e2d8SCharles.Forsyth skip(); 101*0d13e2d8SCharles.Forsyth } 102*0d13e2d8SCharles.Forsyth if(0 && debug) 103*0d13e2d8SCharles.Forsyth prtree(e, 0); 104*0d13e2d8SCharles.Forsyth if(e != nil && e.op != Ofn){ 105*0d13e2d8SCharles.Forsyth (k, v) := (Onothing, 0.0); 106*0d13e2d8SCharles.Forsyth { 107*0d13e2d8SCharles.Forsyth (k, v) = estat(e); 108*0d13e2d8SCharles.Forsyth } 109*0d13e2d8SCharles.Forsyth exception ex{ 110*0d13e2d8SCharles.Forsyth "*" => 111*0d13e2d8SCharles.Forsyth e = nil; 112*0d13e2d8SCharles.Forsyth err(ex); 113*0d13e2d8SCharles.Forsyth } 114*0d13e2d8SCharles.Forsyth if(pexp(e)) 115*0d13e2d8SCharles.Forsyth printnum(v, "\n"); 116*0d13e2d8SCharles.Forsyth if(k == Oexit) 117*0d13e2d8SCharles.Forsyth exit; 118*0d13e2d8SCharles.Forsyth } 119*0d13e2d8SCharles.Forsyth } 120*0d13e2d8SCharles.Forsyth popscope(); 121*0d13e2d8SCharles.Forsyth popscope(); 122*0d13e2d8SCharles.Forsyth} 123*0d13e2d8SCharles.Forsyth 124*0d13e2d8SCharles.Forsythbits: int; 125*0d13e2d8SCharles.Forsythdebug: int; 126*0d13e2d8SCharles.Forsythstrict: int; 127*0d13e2d8SCharles.Forsyth 128*0d13e2d8SCharles.ForsythNone: con -2; 129*0d13e2d8SCharles.ForsythEof: con -1; 130*0d13e2d8SCharles.ForsythEeof: con "eof"; 131*0d13e2d8SCharles.Forsyth 132*0d13e2d8SCharles.ForsythHash: con 16; 133*0d13e2d8SCharles.ForsythBig: con 1<<30; 134*0d13e2d8SCharles.ForsythMaxint: con 16r7FFFFFFF; 135*0d13e2d8SCharles.ForsythNan: con Math->NaN; 136*0d13e2d8SCharles.ForsythInfinity: con Math->Infinity; 137*0d13e2d8SCharles.ForsythPi: con Math->Pi; 138*0d13e2d8SCharles.ForsythEps: con 1E-10; 139*0d13e2d8SCharles.ForsythBigeps: con 1E-2; 140*0d13e2d8SCharles.ForsythLn2: con 0.6931471805599453; 141*0d13e2d8SCharles.ForsythLn10: con 2.302585092994046; 142*0d13e2d8SCharles.ForsythEuler: con 2.71828182845904523536; 143*0d13e2d8SCharles.ForsythGamma: con 0.57721566490153286060; 144*0d13e2d8SCharles.ForsythPhi: con 1.61803398874989484820; 145*0d13e2d8SCharles.Forsyth 146*0d13e2d8SCharles.ForsythOeof, 147*0d13e2d8SCharles.ForsythOstring, Onum, Oident, Ocon, Ovar, Ofun, Olfun, 148*0d13e2d8SCharles.ForsythOadd, Osub, Omul, Odiv, Omod, Oidiv, Oexp, Oand, Oor, Oxor, Olsh, Orsh, 149*0d13e2d8SCharles.ForsythOadde, Osube, Omule, Odive, Omode, Oidive, Oexpe, Oande, Oore, Oxore, Olshe, Orshe, 150*0d13e2d8SCharles.ForsythOeq, One, Ogt, Olt, Oge, Ole, 151*0d13e2d8SCharles.ForsythOinc, Opreinc, Opostinc, Odec, Opredec, Opostdec, 152*0d13e2d8SCharles.ForsythOandand, Ooror, 153*0d13e2d8SCharles.ForsythOexc, Onot, Ofact, Ocom, 154*0d13e2d8SCharles.ForsythOas, Odas, 155*0d13e2d8SCharles.ForsythOplus, Ominus, Oinv, 156*0d13e2d8SCharles.ForsythOcomma, Oscomma, Oquest, Ocolon, 157*0d13e2d8SCharles.ForsythOnand, Onor, Oimp, Oimpby, Oiff, 158*0d13e2d8SCharles.ForsythOlbr, Orbr, Olcbr, Orcbr, Oscolon, Onl, 159*0d13e2d8SCharles.ForsythOnothing, 160*0d13e2d8SCharles.ForsythOprint, Oread, 161*0d13e2d8SCharles.ForsythOif, Oelse, Ofor, Owhile, Odo, Obreak, Ocont, Oexit, Oret, Ofn, Oinclude, 162*0d13e2d8SCharles.ForsythOsigma, Opi, Ocfrac, Oderiv, Ointeg, Osolve, 163*0d13e2d8SCharles.ForsythOlog, Olog10, Olog2, Ologb, Oexpf, Opow, Osqrt, Ocbrt, Ofloor, Oceil, Omin, Omax, Oabs, Ogamma, Osign, Oint, Ofrac, Oround, Oerf, Oatan2, Osin, Ocos, Otan, Oasin, Oacos, Oatan, Osinh, Ocosh, Otanh, Oasinh, Oacosh, Oatanh, Orand, 164*0d13e2d8SCharles.ForsythOlast: con iota; 165*0d13e2d8SCharles.Forsyth 166*0d13e2d8SCharles.ForsythBinary: con (1<<8); 167*0d13e2d8SCharles.ForsythPreunary: con (1<<9); 168*0d13e2d8SCharles.ForsythPostunary: con (1<<10); 169*0d13e2d8SCharles.ForsythAssoc: con (1<<11); 170*0d13e2d8SCharles.ForsythRassoc: con (1<<12); 171*0d13e2d8SCharles.ForsythPrec: con Binary-1; 172*0d13e2d8SCharles.Forsyth 173*0d13e2d8SCharles.Forsythopss := array[Olast] of 174*0d13e2d8SCharles.Forsyth{ 175*0d13e2d8SCharles.Forsyth "eof", 176*0d13e2d8SCharles.Forsyth "string", 177*0d13e2d8SCharles.Forsyth "number", 178*0d13e2d8SCharles.Forsyth "identifier", 179*0d13e2d8SCharles.Forsyth "constant", 180*0d13e2d8SCharles.Forsyth "variable", 181*0d13e2d8SCharles.Forsyth "function", 182*0d13e2d8SCharles.Forsyth "library function", 183*0d13e2d8SCharles.Forsyth "+", 184*0d13e2d8SCharles.Forsyth "-", 185*0d13e2d8SCharles.Forsyth "*", 186*0d13e2d8SCharles.Forsyth "/", 187*0d13e2d8SCharles.Forsyth "%", 188*0d13e2d8SCharles.Forsyth "//", 189*0d13e2d8SCharles.Forsyth "&", 190*0d13e2d8SCharles.Forsyth "|", 191*0d13e2d8SCharles.Forsyth "^", 192*0d13e2d8SCharles.Forsyth "<<", 193*0d13e2d8SCharles.Forsyth ">>", 194*0d13e2d8SCharles.Forsyth "+=", 195*0d13e2d8SCharles.Forsyth "-=", 196*0d13e2d8SCharles.Forsyth "*=", 197*0d13e2d8SCharles.Forsyth "/=", 198*0d13e2d8SCharles.Forsyth "%=", 199*0d13e2d8SCharles.Forsyth "//=", 200*0d13e2d8SCharles.Forsyth "&=", 201*0d13e2d8SCharles.Forsyth "|=", 202*0d13e2d8SCharles.Forsyth "^=", 203*0d13e2d8SCharles.Forsyth "<<=", 204*0d13e2d8SCharles.Forsyth ">>=", 205*0d13e2d8SCharles.Forsyth "==", 206*0d13e2d8SCharles.Forsyth "!=", 207*0d13e2d8SCharles.Forsyth ">", 208*0d13e2d8SCharles.Forsyth "<", 209*0d13e2d8SCharles.Forsyth ">=", 210*0d13e2d8SCharles.Forsyth "<=", 211*0d13e2d8SCharles.Forsyth "++", 212*0d13e2d8SCharles.Forsyth "++", 213*0d13e2d8SCharles.Forsyth "++", 214*0d13e2d8SCharles.Forsyth "--", 215*0d13e2d8SCharles.Forsyth "--", 216*0d13e2d8SCharles.Forsyth "--", 217*0d13e2d8SCharles.Forsyth "**", 218*0d13e2d8SCharles.Forsyth "&&", 219*0d13e2d8SCharles.Forsyth "||", 220*0d13e2d8SCharles.Forsyth "!", 221*0d13e2d8SCharles.Forsyth "!", 222*0d13e2d8SCharles.Forsyth "!", 223*0d13e2d8SCharles.Forsyth "~", 224*0d13e2d8SCharles.Forsyth "=", 225*0d13e2d8SCharles.Forsyth ":=", 226*0d13e2d8SCharles.Forsyth "+", 227*0d13e2d8SCharles.Forsyth "-", 228*0d13e2d8SCharles.Forsyth "1/", 229*0d13e2d8SCharles.Forsyth ",", 230*0d13e2d8SCharles.Forsyth ",", 231*0d13e2d8SCharles.Forsyth "?", 232*0d13e2d8SCharles.Forsyth ":", 233*0d13e2d8SCharles.Forsyth "↑", 234*0d13e2d8SCharles.Forsyth "↓", 235*0d13e2d8SCharles.Forsyth "->", 236*0d13e2d8SCharles.Forsyth "<-", 237*0d13e2d8SCharles.Forsyth "<->", 238*0d13e2d8SCharles.Forsyth "(", 239*0d13e2d8SCharles.Forsyth ")", 240*0d13e2d8SCharles.Forsyth "{", 241*0d13e2d8SCharles.Forsyth "}", 242*0d13e2d8SCharles.Forsyth ";", 243*0d13e2d8SCharles.Forsyth "\n", 244*0d13e2d8SCharles.Forsyth "", 245*0d13e2d8SCharles.Forsyth}; 246*0d13e2d8SCharles.Forsyth 247*0d13e2d8SCharles.Forsythops := array[Olast] of 248*0d13e2d8SCharles.Forsyth{ 249*0d13e2d8SCharles.Forsyth Oeof => 0, 250*0d13e2d8SCharles.Forsyth Ostring => 17, 251*0d13e2d8SCharles.Forsyth Onum => 17, 252*0d13e2d8SCharles.Forsyth Oident => 17, 253*0d13e2d8SCharles.Forsyth Ocon => 17, 254*0d13e2d8SCharles.Forsyth Ovar => 17, 255*0d13e2d8SCharles.Forsyth Ofun => 17, 256*0d13e2d8SCharles.Forsyth Olfun => 17, 257*0d13e2d8SCharles.Forsyth Oadd => 12|Binary|Assoc|Preunary, 258*0d13e2d8SCharles.Forsyth Osub => 12|Binary|Preunary, 259*0d13e2d8SCharles.Forsyth Omul => 13|Binary|Assoc, 260*0d13e2d8SCharles.Forsyth Odiv => 13|Binary, 261*0d13e2d8SCharles.Forsyth Omod => 13|Binary, 262*0d13e2d8SCharles.Forsyth Oidiv => 13|Binary, 263*0d13e2d8SCharles.Forsyth Oexp => 14|Binary|Rassoc, 264*0d13e2d8SCharles.Forsyth Oand => 8|Binary|Assoc, 265*0d13e2d8SCharles.Forsyth Oor => 6|Binary|Assoc, 266*0d13e2d8SCharles.Forsyth Oxor => 7|Binary|Assoc, 267*0d13e2d8SCharles.Forsyth Olsh => 11|Binary, 268*0d13e2d8SCharles.Forsyth Orsh => 11|Binary, 269*0d13e2d8SCharles.Forsyth Oadde => 2|Binary|Rassoc, 270*0d13e2d8SCharles.Forsyth Osube => 2|Binary|Rassoc, 271*0d13e2d8SCharles.Forsyth Omule => 2|Binary|Rassoc, 272*0d13e2d8SCharles.Forsyth Odive => 2|Binary|Rassoc, 273*0d13e2d8SCharles.Forsyth Omode => 2|Binary|Rassoc, 274*0d13e2d8SCharles.Forsyth Oidive => 2|Binary|Rassoc, 275*0d13e2d8SCharles.Forsyth Oexpe => 2|Binary|Rassoc, 276*0d13e2d8SCharles.Forsyth Oande => 2|Binary|Rassoc, 277*0d13e2d8SCharles.Forsyth Oore => 2|Binary|Rassoc, 278*0d13e2d8SCharles.Forsyth Oxore => 2|Binary|Rassoc, 279*0d13e2d8SCharles.Forsyth Olshe => 2|Binary|Rassoc, 280*0d13e2d8SCharles.Forsyth Orshe => 2|Binary|Rassoc, 281*0d13e2d8SCharles.Forsyth Oeq => 9|Binary, 282*0d13e2d8SCharles.Forsyth One => 9|Binary, 283*0d13e2d8SCharles.Forsyth Ogt => 10|Binary, 284*0d13e2d8SCharles.Forsyth Olt => 10|Binary, 285*0d13e2d8SCharles.Forsyth Oge => 10|Binary, 286*0d13e2d8SCharles.Forsyth Ole => 10|Binary, 287*0d13e2d8SCharles.Forsyth Oinc => 15|Rassoc|Preunary|Postunary, 288*0d13e2d8SCharles.Forsyth Opreinc => 15|Rassoc|Preunary, 289*0d13e2d8SCharles.Forsyth Opostinc => 15|Rassoc|Postunary, 290*0d13e2d8SCharles.Forsyth Odec => 15|Rassoc|Preunary|Postunary, 291*0d13e2d8SCharles.Forsyth Opredec => 15|Rassoc|Preunary, 292*0d13e2d8SCharles.Forsyth Opostdec => 15|Rassoc|Postunary, 293*0d13e2d8SCharles.Forsyth Oandand => 5|Binary|Assoc, 294*0d13e2d8SCharles.Forsyth Ooror => 4|Binary|Assoc, 295*0d13e2d8SCharles.Forsyth Oexc => 15|Rassoc|Preunary|Postunary, 296*0d13e2d8SCharles.Forsyth Onot => 15|Rassoc|Preunary, 297*0d13e2d8SCharles.Forsyth Ofact => 15|Rassoc|Postunary, 298*0d13e2d8SCharles.Forsyth Ocom => 15|Rassoc|Preunary, 299*0d13e2d8SCharles.Forsyth Oas => 2|Binary|Rassoc, 300*0d13e2d8SCharles.Forsyth Odas => 2|Binary|Rassoc, 301*0d13e2d8SCharles.Forsyth Oplus => 15|Rassoc|Preunary, 302*0d13e2d8SCharles.Forsyth Ominus => 15|Rassoc|Preunary, 303*0d13e2d8SCharles.Forsyth Oinv => 15|Rassoc|Postunary, 304*0d13e2d8SCharles.Forsyth Ocomma => 1|Binary|Assoc, 305*0d13e2d8SCharles.Forsyth Oscomma => 1|Binary|Assoc, 306*0d13e2d8SCharles.Forsyth Oquest => 3|Binary|Rassoc, 307*0d13e2d8SCharles.Forsyth Ocolon => 3|Binary|Rassoc, 308*0d13e2d8SCharles.Forsyth Onand => 8|Binary, 309*0d13e2d8SCharles.Forsyth Onor => 6|Binary, 310*0d13e2d8SCharles.Forsyth Oimp => 9|Binary, 311*0d13e2d8SCharles.Forsyth Oimpby => 9|Binary, 312*0d13e2d8SCharles.Forsyth Oiff => 10|Binary|Assoc, 313*0d13e2d8SCharles.Forsyth Olbr => 16, 314*0d13e2d8SCharles.Forsyth Orbr => 16, 315*0d13e2d8SCharles.Forsyth Onothing => 0, 316*0d13e2d8SCharles.Forsyth}; 317*0d13e2d8SCharles.Forsyth 318*0d13e2d8SCharles.ForsythDeg: con "degrees"; 319*0d13e2d8SCharles.ForsythBase: con "printbase"; 320*0d13e2d8SCharles.ForsythLimit: con "solvelimit"; 321*0d13e2d8SCharles.ForsythStep: con "solvestep"; 322*0d13e2d8SCharles.Forsyth 323*0d13e2d8SCharles.Forsythkeyw := array[] of 324*0d13e2d8SCharles.Forsyth{ 325*0d13e2d8SCharles.Forsyth ("include", Oinclude), 326*0d13e2d8SCharles.Forsyth ("if", Oif), 327*0d13e2d8SCharles.Forsyth ("else", Oelse), 328*0d13e2d8SCharles.Forsyth ("for", Ofor), 329*0d13e2d8SCharles.Forsyth ("while", Owhile), 330*0d13e2d8SCharles.Forsyth ("do", Odo), 331*0d13e2d8SCharles.Forsyth ("break", Obreak), 332*0d13e2d8SCharles.Forsyth ("continue", Ocont), 333*0d13e2d8SCharles.Forsyth ("exit", Oexit), 334*0d13e2d8SCharles.Forsyth ("return", Oret), 335*0d13e2d8SCharles.Forsyth ("print", Oprint), 336*0d13e2d8SCharles.Forsyth ("read", Oread), 337*0d13e2d8SCharles.Forsyth ("fn", Ofn), 338*0d13e2d8SCharles.Forsyth ("", 0), 339*0d13e2d8SCharles.Forsyth}; 340*0d13e2d8SCharles.Forsyth 341*0d13e2d8SCharles.Forsythconw := array[] of 342*0d13e2d8SCharles.Forsyth{ 343*0d13e2d8SCharles.Forsyth ("π", Pi), 344*0d13e2d8SCharles.Forsyth ("Pi", Pi), 345*0d13e2d8SCharles.Forsyth ("e", Euler), 346*0d13e2d8SCharles.Forsyth ("γ", Gamma), 347*0d13e2d8SCharles.Forsyth ("Gamma", Gamma), 348*0d13e2d8SCharles.Forsyth ("φ", Phi), 349*0d13e2d8SCharles.Forsyth ("Phi", Phi), 350*0d13e2d8SCharles.Forsyth ("∞", Infinity), 351*0d13e2d8SCharles.Forsyth ("Infinity", Infinity), 352*0d13e2d8SCharles.Forsyth ("NaN", Nan), 353*0d13e2d8SCharles.Forsyth ("Nan", Nan), 354*0d13e2d8SCharles.Forsyth ("nan", Nan), 355*0d13e2d8SCharles.Forsyth ("", 0.0), 356*0d13e2d8SCharles.Forsyth}; 357*0d13e2d8SCharles.Forsyth 358*0d13e2d8SCharles.Forsythvarw := array[] of 359*0d13e2d8SCharles.Forsyth{ 360*0d13e2d8SCharles.Forsyth (Deg, 0.0), 361*0d13e2d8SCharles.Forsyth (Base, 10.0), 362*0d13e2d8SCharles.Forsyth (Limit, 100.0), 363*0d13e2d8SCharles.Forsyth (Step, 1.0), 364*0d13e2d8SCharles.Forsyth ("", 0.0), 365*0d13e2d8SCharles.Forsyth}; 366*0d13e2d8SCharles.Forsyth 367*0d13e2d8SCharles.Forsythfunw := array[] of 368*0d13e2d8SCharles.Forsyth{ 369*0d13e2d8SCharles.Forsyth ("log", Olog, 1), 370*0d13e2d8SCharles.Forsyth ("ln", Olog, 1), 371*0d13e2d8SCharles.Forsyth ("log10", Olog10, 1), 372*0d13e2d8SCharles.Forsyth ("log2", Olog2, 1), 373*0d13e2d8SCharles.Forsyth ("logb", Ologb, 2), 374*0d13e2d8SCharles.Forsyth ("exp", Oexpf, 1), 375*0d13e2d8SCharles.Forsyth ("pow", Opow, 2), 376*0d13e2d8SCharles.Forsyth ("sqrt", Osqrt, 1), 377*0d13e2d8SCharles.Forsyth ("cbrt", Ocbrt, 1), 378*0d13e2d8SCharles.Forsyth ("floor", Ofloor, 1), 379*0d13e2d8SCharles.Forsyth ("ceiling", Oceil, 1), 380*0d13e2d8SCharles.Forsyth ("min", Omin, 2), 381*0d13e2d8SCharles.Forsyth ("max", Omax, 2), 382*0d13e2d8SCharles.Forsyth ("abs", Oabs, 1), 383*0d13e2d8SCharles.Forsyth ("Γ", Ogamma, 1), 384*0d13e2d8SCharles.Forsyth ("gamma", Ogamma, 1), 385*0d13e2d8SCharles.Forsyth ("sign", Osign, 1), 386*0d13e2d8SCharles.Forsyth ("int", Oint, 1), 387*0d13e2d8SCharles.Forsyth ("frac", Ofrac, 1), 388*0d13e2d8SCharles.Forsyth ("round", Oround, 1), 389*0d13e2d8SCharles.Forsyth ("erf", Oerf, 1), 390*0d13e2d8SCharles.Forsyth ("atan2", Oatan2, 2), 391*0d13e2d8SCharles.Forsyth ("sin", Osin, 1), 392*0d13e2d8SCharles.Forsyth ("cos", Ocos, 1), 393*0d13e2d8SCharles.Forsyth ("tan", Otan, 1), 394*0d13e2d8SCharles.Forsyth ("asin", Oasin, 1), 395*0d13e2d8SCharles.Forsyth ("acos", Oacos, 1), 396*0d13e2d8SCharles.Forsyth ("atan", Oatan, 1), 397*0d13e2d8SCharles.Forsyth ("sinh", Osinh, 1), 398*0d13e2d8SCharles.Forsyth ("cosh", Ocosh, 1), 399*0d13e2d8SCharles.Forsyth ("tanh", Otanh, 1), 400*0d13e2d8SCharles.Forsyth ("asinh", Oasinh, 1), 401*0d13e2d8SCharles.Forsyth ("acosh", Oacosh, 1), 402*0d13e2d8SCharles.Forsyth ("atanh", Oatanh, 1), 403*0d13e2d8SCharles.Forsyth ("rand", Orand, 0), 404*0d13e2d8SCharles.Forsyth ("Σ", Osigma, 3), 405*0d13e2d8SCharles.Forsyth ("sigma", Osigma, 3), 406*0d13e2d8SCharles.Forsyth ("Π", Opi, 3), 407*0d13e2d8SCharles.Forsyth ("pi", Opi, 3), 408*0d13e2d8SCharles.Forsyth ("cfrac", Ocfrac, 3), 409*0d13e2d8SCharles.Forsyth ("Δ", Oderiv, 2), 410*0d13e2d8SCharles.Forsyth ("differential", Oderiv, 2), 411*0d13e2d8SCharles.Forsyth ("∫", Ointeg, 3), 412*0d13e2d8SCharles.Forsyth ("integral", Ointeg, 3), 413*0d13e2d8SCharles.Forsyth ("solve", Osolve, 1), 414*0d13e2d8SCharles.Forsyth ("", 0, 0), 415*0d13e2d8SCharles.Forsyth}; 416*0d13e2d8SCharles.Forsyth 417*0d13e2d8SCharles.Forsythstdin: int; 418*0d13e2d8SCharles.Forsythbin: ref Iobuf; 419*0d13e2d8SCharles.Forsythlineno: int = 1; 420*0d13e2d8SCharles.Forsythfile: string; 421*0d13e2d8SCharles.Forsythiostack: list of (int, int, int, string, ref Iobuf); 422*0d13e2d8SCharles.Forsythgeof: int; 423*0d13e2d8SCharles.Forsythgarg: string; 424*0d13e2d8SCharles.Forsythgargs: list of string; 425*0d13e2d8SCharles.Forsythbufc: int = None; 426*0d13e2d8SCharles.Forsythbuft: int = Olast; 427*0d13e2d8SCharles.Forsythlexes: int; 428*0d13e2d8SCharles.Forsythlexval: real; 429*0d13e2d8SCharles.Forsythlexstr: string; 430*0d13e2d8SCharles.Forsythlexsym: ref Sym; 431*0d13e2d8SCharles.Forsythsyms: array of ref Sym; 432*0d13e2d8SCharles.Forsythdeg: ref Dec; 433*0d13e2d8SCharles.Forsythpbase: ref Dec; 434*0d13e2d8SCharles.Forsytherrdec: ref Dec; 435*0d13e2d8SCharles.Forsythinloop: int; 436*0d13e2d8SCharles.Forsythinfn: int; 437*0d13e2d8SCharles.Forsyth 438*0d13e2d8SCharles.ForsythNode: adt 439*0d13e2d8SCharles.Forsyth{ 440*0d13e2d8SCharles.Forsyth op: int; 441*0d13e2d8SCharles.Forsyth left: cyclic ref Node; 442*0d13e2d8SCharles.Forsyth right: cyclic ref Node; 443*0d13e2d8SCharles.Forsyth val: real; 444*0d13e2d8SCharles.Forsyth str: string; 445*0d13e2d8SCharles.Forsyth dec: cyclic ref Dec; 446*0d13e2d8SCharles.Forsyth src: int; 447*0d13e2d8SCharles.Forsyth}; 448*0d13e2d8SCharles.Forsyth 449*0d13e2d8SCharles.ForsythDec: adt 450*0d13e2d8SCharles.Forsyth{ 451*0d13e2d8SCharles.Forsyth kind: int; 452*0d13e2d8SCharles.Forsyth scope: int; 453*0d13e2d8SCharles.Forsyth sym: cyclic ref Sym; 454*0d13e2d8SCharles.Forsyth val: real; 455*0d13e2d8SCharles.Forsyth na: int; 456*0d13e2d8SCharles.Forsyth code: cyclic ref Node; 457*0d13e2d8SCharles.Forsyth old: cyclic ref Dec; 458*0d13e2d8SCharles.Forsyth next: cyclic ref Dec; 459*0d13e2d8SCharles.Forsyth}; 460*0d13e2d8SCharles.Forsyth 461*0d13e2d8SCharles.ForsythSym: adt 462*0d13e2d8SCharles.Forsyth{ 463*0d13e2d8SCharles.Forsyth name: string; 464*0d13e2d8SCharles.Forsyth kind: int; 465*0d13e2d8SCharles.Forsyth dec: cyclic ref Dec; 466*0d13e2d8SCharles.Forsyth next: cyclic ref Sym; 467*0d13e2d8SCharles.Forsyth}; 468*0d13e2d8SCharles.Forsyth 469*0d13e2d8SCharles.Forsythopstring(t: int): string 470*0d13e2d8SCharles.Forsyth{ 471*0d13e2d8SCharles.Forsyth s := opss[t]; 472*0d13e2d8SCharles.Forsyth if(s != nil) 473*0d13e2d8SCharles.Forsyth return s; 474*0d13e2d8SCharles.Forsyth for(i := 0; keyw[i].t0 != nil; i++) 475*0d13e2d8SCharles.Forsyth if(t == keyw[i].t1) 476*0d13e2d8SCharles.Forsyth return keyw[i].t0; 477*0d13e2d8SCharles.Forsyth for(i = 0; funw[i].t0 != nil; i++) 478*0d13e2d8SCharles.Forsyth if(t == funw[i].t1) 479*0d13e2d8SCharles.Forsyth return funw[i].t0; 480*0d13e2d8SCharles.Forsyth return s; 481*0d13e2d8SCharles.Forsyth} 482*0d13e2d8SCharles.Forsyth 483*0d13e2d8SCharles.Forsytherr(s: string) 484*0d13e2d8SCharles.Forsyth{ 485*0d13e2d8SCharles.Forsyth sys->print("error: %s\n", s); 486*0d13e2d8SCharles.Forsyth} 487*0d13e2d8SCharles.Forsyth 488*0d13e2d8SCharles.Forsytherror(n: ref Node, s: string) 489*0d13e2d8SCharles.Forsyth{ 490*0d13e2d8SCharles.Forsyth if(n != nil) 491*0d13e2d8SCharles.Forsyth lno := n.src; 492*0d13e2d8SCharles.Forsyth else 493*0d13e2d8SCharles.Forsyth lno = lineno; 494*0d13e2d8SCharles.Forsyth s = sys->sprint("line %d: %s", lno, s); 495*0d13e2d8SCharles.Forsyth if(file != nil) 496*0d13e2d8SCharles.Forsyth s = sys->sprint("file %s: %s", file, s); 497*0d13e2d8SCharles.Forsyth raise s; 498*0d13e2d8SCharles.Forsyth} 499*0d13e2d8SCharles.Forsyth 500*0d13e2d8SCharles.Forsythfatal(s: string) 501*0d13e2d8SCharles.Forsyth{ 502*0d13e2d8SCharles.Forsyth sys->print("fatal: %s\n", s); 503*0d13e2d8SCharles.Forsyth exit; 504*0d13e2d8SCharles.Forsyth} 505*0d13e2d8SCharles.Forsyth 506*0d13e2d8SCharles.Forsythstack(s: string, f: ref Iobuf) 507*0d13e2d8SCharles.Forsyth{ 508*0d13e2d8SCharles.Forsyth iostack = (bufc, buft, lineno, file, bin) :: iostack; 509*0d13e2d8SCharles.Forsyth bufc = None; 510*0d13e2d8SCharles.Forsyth buft = Olast; 511*0d13e2d8SCharles.Forsyth lineno = 1; 512*0d13e2d8SCharles.Forsyth file = s; 513*0d13e2d8SCharles.Forsyth bin = f; 514*0d13e2d8SCharles.Forsyth} 515*0d13e2d8SCharles.Forsyth 516*0d13e2d8SCharles.Forsythunstack() 517*0d13e2d8SCharles.Forsyth{ 518*0d13e2d8SCharles.Forsyth (bufc, buft, lineno, file, bin) = hd iostack; 519*0d13e2d8SCharles.Forsyth iostack = tl iostack; 520*0d13e2d8SCharles.Forsyth} 521*0d13e2d8SCharles.Forsyth 522*0d13e2d8SCharles.Forsythdoinclude(s: string) 523*0d13e2d8SCharles.Forsyth{ 524*0d13e2d8SCharles.Forsyth f := bufio->open(s, Sys->OREAD); 525*0d13e2d8SCharles.Forsyth if(f == nil) 526*0d13e2d8SCharles.Forsyth error(nil, sys->sprint("cannot open %s", s)); 527*0d13e2d8SCharles.Forsyth stack(s, f); 528*0d13e2d8SCharles.Forsyth} 529*0d13e2d8SCharles.Forsyth 530*0d13e2d8SCharles.Forsythgetc(): int 531*0d13e2d8SCharles.Forsyth{ 532*0d13e2d8SCharles.Forsyth if((c := bufc) != None) 533*0d13e2d8SCharles.Forsyth bufc = None; 534*0d13e2d8SCharles.Forsyth else if(bin != nil) 535*0d13e2d8SCharles.Forsyth c = bin.getc(); 536*0d13e2d8SCharles.Forsyth else{ 537*0d13e2d8SCharles.Forsyth if(garg == nil){ 538*0d13e2d8SCharles.Forsyth if(gargs == nil){ 539*0d13e2d8SCharles.Forsyth if(geof == 0){ 540*0d13e2d8SCharles.Forsyth geof = 1; 541*0d13e2d8SCharles.Forsyth c = '\n'; 542*0d13e2d8SCharles.Forsyth } 543*0d13e2d8SCharles.Forsyth else 544*0d13e2d8SCharles.Forsyth c = Eof; 545*0d13e2d8SCharles.Forsyth } 546*0d13e2d8SCharles.Forsyth else{ 547*0d13e2d8SCharles.Forsyth garg = hd gargs; 548*0d13e2d8SCharles.Forsyth gargs = tl gargs; 549*0d13e2d8SCharles.Forsyth c = ' '; 550*0d13e2d8SCharles.Forsyth } 551*0d13e2d8SCharles.Forsyth } 552*0d13e2d8SCharles.Forsyth else{ 553*0d13e2d8SCharles.Forsyth c = garg[0]; 554*0d13e2d8SCharles.Forsyth garg = garg[1: ]; 555*0d13e2d8SCharles.Forsyth } 556*0d13e2d8SCharles.Forsyth } 557*0d13e2d8SCharles.Forsyth if(c == Eof && iostack != nil){ 558*0d13e2d8SCharles.Forsyth unstack(); 559*0d13e2d8SCharles.Forsyth return getc(); 560*0d13e2d8SCharles.Forsyth } 561*0d13e2d8SCharles.Forsyth return c; 562*0d13e2d8SCharles.Forsyth} 563*0d13e2d8SCharles.Forsyth 564*0d13e2d8SCharles.Forsythungetc(c: int) 565*0d13e2d8SCharles.Forsyth{ 566*0d13e2d8SCharles.Forsyth bufc = c; 567*0d13e2d8SCharles.Forsyth} 568*0d13e2d8SCharles.Forsyth 569*0d13e2d8SCharles.Forsythslash(c: int): int 570*0d13e2d8SCharles.Forsyth{ 571*0d13e2d8SCharles.Forsyth if(c != '\\') 572*0d13e2d8SCharles.Forsyth return c; 573*0d13e2d8SCharles.Forsyth nc := getc(); 574*0d13e2d8SCharles.Forsyth case(nc){ 575*0d13e2d8SCharles.Forsyth 'b' => return '\b'; 576*0d13e2d8SCharles.Forsyth 'f' => return '\f'; 577*0d13e2d8SCharles.Forsyth 'n' => return '\n'; 578*0d13e2d8SCharles.Forsyth 'r' => return '\r'; 579*0d13e2d8SCharles.Forsyth 't' => return '\t'; 580*0d13e2d8SCharles.Forsyth } 581*0d13e2d8SCharles.Forsyth return nc; 582*0d13e2d8SCharles.Forsyth} 583*0d13e2d8SCharles.Forsyth 584*0d13e2d8SCharles.Forsythlexstring(): int 585*0d13e2d8SCharles.Forsyth{ 586*0d13e2d8SCharles.Forsyth sp := ""; 587*0d13e2d8SCharles.Forsyth while((c := getc()) != '"'){ 588*0d13e2d8SCharles.Forsyth if(c == Eof) 589*0d13e2d8SCharles.Forsyth raise Eeof; 590*0d13e2d8SCharles.Forsyth sp[len sp] = slash(c); 591*0d13e2d8SCharles.Forsyth } 592*0d13e2d8SCharles.Forsyth lexstr = sp; 593*0d13e2d8SCharles.Forsyth return Ostring; 594*0d13e2d8SCharles.Forsyth} 595*0d13e2d8SCharles.Forsyth 596*0d13e2d8SCharles.Forsythlexchar(): int 597*0d13e2d8SCharles.Forsyth{ 598*0d13e2d8SCharles.Forsyth while((c := getc()) != '\''){ 599*0d13e2d8SCharles.Forsyth if(c == Eof) 600*0d13e2d8SCharles.Forsyth raise Eeof; 601*0d13e2d8SCharles.Forsyth lexval = real slash(c); 602*0d13e2d8SCharles.Forsyth } 603*0d13e2d8SCharles.Forsyth return Onum; 604*0d13e2d8SCharles.Forsyth} 605*0d13e2d8SCharles.Forsyth 606*0d13e2d8SCharles.Forsythbasev(c: int, base: int): int 607*0d13e2d8SCharles.Forsyth{ 608*0d13e2d8SCharles.Forsyth if(c >= 'a' && c <= 'z') 609*0d13e2d8SCharles.Forsyth c += 10-'a'; 610*0d13e2d8SCharles.Forsyth else if(c >= 'A' && c <= 'Z') 611*0d13e2d8SCharles.Forsyth c += 10-'A'; 612*0d13e2d8SCharles.Forsyth else if(c >= '0' && c <= '9') 613*0d13e2d8SCharles.Forsyth c -= '0'; 614*0d13e2d8SCharles.Forsyth else 615*0d13e2d8SCharles.Forsyth return -1; 616*0d13e2d8SCharles.Forsyth if(c >= base) 617*0d13e2d8SCharles.Forsyth error(nil, "bad digit"); 618*0d13e2d8SCharles.Forsyth return c; 619*0d13e2d8SCharles.Forsyth} 620*0d13e2d8SCharles.Forsyth 621*0d13e2d8SCharles.Forsythlexe(base: int): int 622*0d13e2d8SCharles.Forsyth{ 623*0d13e2d8SCharles.Forsyth neg := 0; 624*0d13e2d8SCharles.Forsyth v := big 0; 625*0d13e2d8SCharles.Forsyth c := getc(); 626*0d13e2d8SCharles.Forsyth if(c == '-') 627*0d13e2d8SCharles.Forsyth neg = 1; 628*0d13e2d8SCharles.Forsyth else 629*0d13e2d8SCharles.Forsyth ungetc(c); 630*0d13e2d8SCharles.Forsyth for(;;){ 631*0d13e2d8SCharles.Forsyth c = getc(); 632*0d13e2d8SCharles.Forsyth cc := basev(c, base); 633*0d13e2d8SCharles.Forsyth if(cc < 0){ 634*0d13e2d8SCharles.Forsyth ungetc(c); 635*0d13e2d8SCharles.Forsyth break; 636*0d13e2d8SCharles.Forsyth } 637*0d13e2d8SCharles.Forsyth v = big base*v+big cc; 638*0d13e2d8SCharles.Forsyth } 639*0d13e2d8SCharles.Forsyth if(neg) 640*0d13e2d8SCharles.Forsyth v = -v; 641*0d13e2d8SCharles.Forsyth return int v; 642*0d13e2d8SCharles.Forsyth} 643*0d13e2d8SCharles.Forsyth 644*0d13e2d8SCharles.Forsythlexnum(): int 645*0d13e2d8SCharles.Forsyth{ 646*0d13e2d8SCharles.Forsyth base := 10; 647*0d13e2d8SCharles.Forsyth exp := 0; 648*0d13e2d8SCharles.Forsyth r := f := e := 0; 649*0d13e2d8SCharles.Forsyth v := big 0; 650*0d13e2d8SCharles.Forsyth c := getc(); 651*0d13e2d8SCharles.Forsyth if(c == '0'){ 652*0d13e2d8SCharles.Forsyth base = 8; 653*0d13e2d8SCharles.Forsyth c = getc(); 654*0d13e2d8SCharles.Forsyth if(c == '.'){ 655*0d13e2d8SCharles.Forsyth base = 10; 656*0d13e2d8SCharles.Forsyth ungetc(c); 657*0d13e2d8SCharles.Forsyth } 658*0d13e2d8SCharles.Forsyth else if(c == 'x' || c == 'X') 659*0d13e2d8SCharles.Forsyth base = 16; 660*0d13e2d8SCharles.Forsyth else 661*0d13e2d8SCharles.Forsyth ungetc(c); 662*0d13e2d8SCharles.Forsyth } 663*0d13e2d8SCharles.Forsyth else 664*0d13e2d8SCharles.Forsyth ungetc(c); 665*0d13e2d8SCharles.Forsyth for(;;){ 666*0d13e2d8SCharles.Forsyth c = getc(); 667*0d13e2d8SCharles.Forsyth if(!r && (c == 'r' || c == 'R')){ 668*0d13e2d8SCharles.Forsyth if(f || e) 669*0d13e2d8SCharles.Forsyth error(nil, "bad base"); 670*0d13e2d8SCharles.Forsyth r = 1; 671*0d13e2d8SCharles.Forsyth base = int v; 672*0d13e2d8SCharles.Forsyth if(base < 2 || base > 36) 673*0d13e2d8SCharles.Forsyth error(nil, "bad base"); 674*0d13e2d8SCharles.Forsyth v = big 0; 675*0d13e2d8SCharles.Forsyth continue; 676*0d13e2d8SCharles.Forsyth } 677*0d13e2d8SCharles.Forsyth if(c == '.'){ 678*0d13e2d8SCharles.Forsyth if(f || e) 679*0d13e2d8SCharles.Forsyth error(nil, "bad real"); 680*0d13e2d8SCharles.Forsyth f = 1; 681*0d13e2d8SCharles.Forsyth continue; 682*0d13e2d8SCharles.Forsyth } 683*0d13e2d8SCharles.Forsyth if(base == 10 && (c == 'e' || c == 'E')){ 684*0d13e2d8SCharles.Forsyth if(e) 685*0d13e2d8SCharles.Forsyth error(nil, "bad E part"); 686*0d13e2d8SCharles.Forsyth e = 1; 687*0d13e2d8SCharles.Forsyth exp = lexe(base); 688*0d13e2d8SCharles.Forsyth continue; 689*0d13e2d8SCharles.Forsyth } 690*0d13e2d8SCharles.Forsyth cc := basev(c, base); 691*0d13e2d8SCharles.Forsyth if(cc < 0){ 692*0d13e2d8SCharles.Forsyth ungetc(c); 693*0d13e2d8SCharles.Forsyth break; 694*0d13e2d8SCharles.Forsyth } 695*0d13e2d8SCharles.Forsyth v = big base*v+big cc; 696*0d13e2d8SCharles.Forsyth if(f) 697*0d13e2d8SCharles.Forsyth f++; 698*0d13e2d8SCharles.Forsyth } 699*0d13e2d8SCharles.Forsyth lexval = real v; 700*0d13e2d8SCharles.Forsyth if(f) 701*0d13e2d8SCharles.Forsyth lexval /= real base**(f-1); 702*0d13e2d8SCharles.Forsyth if(exp){ 703*0d13e2d8SCharles.Forsyth if(exp > 0) 704*0d13e2d8SCharles.Forsyth lexval *= real base**exp; 705*0d13e2d8SCharles.Forsyth else 706*0d13e2d8SCharles.Forsyth lexval *= maths->pow(real base, real exp); 707*0d13e2d8SCharles.Forsyth } 708*0d13e2d8SCharles.Forsyth return Onum; 709*0d13e2d8SCharles.Forsyth} 710*0d13e2d8SCharles.Forsyth 711*0d13e2d8SCharles.Forsythlexid(): int 712*0d13e2d8SCharles.Forsyth{ 713*0d13e2d8SCharles.Forsyth sp := ""; 714*0d13e2d8SCharles.Forsyth for(;;){ 715*0d13e2d8SCharles.Forsyth c := getc(); 716*0d13e2d8SCharles.Forsyth if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c >= 'α' && c <= 'ω' || c >= 'Α' && c <= 'Ω' || c == '_') 717*0d13e2d8SCharles.Forsyth sp[len sp] = c; 718*0d13e2d8SCharles.Forsyth else{ 719*0d13e2d8SCharles.Forsyth ungetc(c); 720*0d13e2d8SCharles.Forsyth break; 721*0d13e2d8SCharles.Forsyth } 722*0d13e2d8SCharles.Forsyth } 723*0d13e2d8SCharles.Forsyth lexsym = enter(sp, Oident); 724*0d13e2d8SCharles.Forsyth return lexsym.kind; 725*0d13e2d8SCharles.Forsyth} 726*0d13e2d8SCharles.Forsyth 727*0d13e2d8SCharles.Forsythfollow(c: int, c1: int, c2: int): int 728*0d13e2d8SCharles.Forsyth{ 729*0d13e2d8SCharles.Forsyth nc := getc(); 730*0d13e2d8SCharles.Forsyth if(nc == c) 731*0d13e2d8SCharles.Forsyth return c1; 732*0d13e2d8SCharles.Forsyth ungetc(nc); 733*0d13e2d8SCharles.Forsyth return c2; 734*0d13e2d8SCharles.Forsyth} 735*0d13e2d8SCharles.Forsyth 736*0d13e2d8SCharles.Forsythskip() 737*0d13e2d8SCharles.Forsyth{ 738*0d13e2d8SCharles.Forsyth if((t := buft) != Olast){ 739*0d13e2d8SCharles.Forsyth lex(); 740*0d13e2d8SCharles.Forsyth if(t == Onl) 741*0d13e2d8SCharles.Forsyth return; 742*0d13e2d8SCharles.Forsyth } 743*0d13e2d8SCharles.Forsyth for(;;){ 744*0d13e2d8SCharles.Forsyth c := getc(); 745*0d13e2d8SCharles.Forsyth if(c == Eof){ 746*0d13e2d8SCharles.Forsyth ungetc(c); 747*0d13e2d8SCharles.Forsyth return; 748*0d13e2d8SCharles.Forsyth } 749*0d13e2d8SCharles.Forsyth if(c == '\n'){ 750*0d13e2d8SCharles.Forsyth lineno++; 751*0d13e2d8SCharles.Forsyth return; 752*0d13e2d8SCharles.Forsyth } 753*0d13e2d8SCharles.Forsyth } 754*0d13e2d8SCharles.Forsyth} 755*0d13e2d8SCharles.Forsyth 756*0d13e2d8SCharles.Forsythlex(): int 757*0d13e2d8SCharles.Forsyth{ 758*0d13e2d8SCharles.Forsyth lexes++; 759*0d13e2d8SCharles.Forsyth if((t := buft) != Olast){ 760*0d13e2d8SCharles.Forsyth buft = Olast; 761*0d13e2d8SCharles.Forsyth if(t == Onl) 762*0d13e2d8SCharles.Forsyth lineno++; 763*0d13e2d8SCharles.Forsyth return t; 764*0d13e2d8SCharles.Forsyth } 765*0d13e2d8SCharles.Forsyth for(;;){ 766*0d13e2d8SCharles.Forsyth case(c := getc()){ 767*0d13e2d8SCharles.Forsyth Eof => 768*0d13e2d8SCharles.Forsyth return Oeof; 769*0d13e2d8SCharles.Forsyth '#' => 770*0d13e2d8SCharles.Forsyth while((c = getc()) != '\n'){ 771*0d13e2d8SCharles.Forsyth if(c == Eof) 772*0d13e2d8SCharles.Forsyth raise Eeof; 773*0d13e2d8SCharles.Forsyth } 774*0d13e2d8SCharles.Forsyth lineno++; 775*0d13e2d8SCharles.Forsyth '\n' => 776*0d13e2d8SCharles.Forsyth lineno++; 777*0d13e2d8SCharles.Forsyth return Onl; 778*0d13e2d8SCharles.Forsyth ' ' or 779*0d13e2d8SCharles.Forsyth '\t' or 780*0d13e2d8SCharles.Forsyth '\r' or 781*0d13e2d8SCharles.Forsyth '\v' => 782*0d13e2d8SCharles.Forsyth ; 783*0d13e2d8SCharles.Forsyth '"' => 784*0d13e2d8SCharles.Forsyth return lexstring(); 785*0d13e2d8SCharles.Forsyth '\'' => 786*0d13e2d8SCharles.Forsyth return lexchar(); 787*0d13e2d8SCharles.Forsyth '0' to '9' => 788*0d13e2d8SCharles.Forsyth ungetc(c); 789*0d13e2d8SCharles.Forsyth return lexnum(); 790*0d13e2d8SCharles.Forsyth 'a' to 'z' or 791*0d13e2d8SCharles.Forsyth 'A' to 'Z' or 792*0d13e2d8SCharles.Forsyth 'α' to 'ω' or 793*0d13e2d8SCharles.Forsyth 'Α' to 'Ω' or 794*0d13e2d8SCharles.Forsyth '_' => 795*0d13e2d8SCharles.Forsyth ungetc(c); 796*0d13e2d8SCharles.Forsyth return lexid(); 797*0d13e2d8SCharles.Forsyth '+' => 798*0d13e2d8SCharles.Forsyth c = getc(); 799*0d13e2d8SCharles.Forsyth if(c == '=') 800*0d13e2d8SCharles.Forsyth return Oadde; 801*0d13e2d8SCharles.Forsyth ungetc(c); 802*0d13e2d8SCharles.Forsyth return follow('+', Oinc, Oadd); 803*0d13e2d8SCharles.Forsyth '-' => 804*0d13e2d8SCharles.Forsyth c = getc(); 805*0d13e2d8SCharles.Forsyth if(c == '=') 806*0d13e2d8SCharles.Forsyth return Osube; 807*0d13e2d8SCharles.Forsyth if(c == '>') 808*0d13e2d8SCharles.Forsyth return Oimp; 809*0d13e2d8SCharles.Forsyth ungetc(c); 810*0d13e2d8SCharles.Forsyth return follow('-', Odec, Osub); 811*0d13e2d8SCharles.Forsyth '*' => 812*0d13e2d8SCharles.Forsyth c = getc(); 813*0d13e2d8SCharles.Forsyth if(c == '=') 814*0d13e2d8SCharles.Forsyth return Omule; 815*0d13e2d8SCharles.Forsyth if(c == '*') 816*0d13e2d8SCharles.Forsyth return follow('=', Oexpe, Oexp); 817*0d13e2d8SCharles.Forsyth ungetc(c); 818*0d13e2d8SCharles.Forsyth return Omul; 819*0d13e2d8SCharles.Forsyth '/' => 820*0d13e2d8SCharles.Forsyth c = getc(); 821*0d13e2d8SCharles.Forsyth if(c == '=') 822*0d13e2d8SCharles.Forsyth return Odive; 823*0d13e2d8SCharles.Forsyth if(c == '/') 824*0d13e2d8SCharles.Forsyth return follow('=', Oidive, Oidiv); 825*0d13e2d8SCharles.Forsyth ungetc(c); 826*0d13e2d8SCharles.Forsyth return Odiv; 827*0d13e2d8SCharles.Forsyth '%' => 828*0d13e2d8SCharles.Forsyth return follow('=', Omode, Omod); 829*0d13e2d8SCharles.Forsyth '&' => 830*0d13e2d8SCharles.Forsyth c = getc(); 831*0d13e2d8SCharles.Forsyth if(c == '=') 832*0d13e2d8SCharles.Forsyth return Oande; 833*0d13e2d8SCharles.Forsyth ungetc(c); 834*0d13e2d8SCharles.Forsyth return follow('&', Oandand, Oand); 835*0d13e2d8SCharles.Forsyth '|' => 836*0d13e2d8SCharles.Forsyth c = getc(); 837*0d13e2d8SCharles.Forsyth if(c == '=') 838*0d13e2d8SCharles.Forsyth return Oore; 839*0d13e2d8SCharles.Forsyth ungetc(c); 840*0d13e2d8SCharles.Forsyth return follow('|', Ooror, Oor); 841*0d13e2d8SCharles.Forsyth '^' => 842*0d13e2d8SCharles.Forsyth return follow('=', Oxore, Oxor); 843*0d13e2d8SCharles.Forsyth '=' => 844*0d13e2d8SCharles.Forsyth return follow('=', Oeq, Oas); 845*0d13e2d8SCharles.Forsyth '!' => 846*0d13e2d8SCharles.Forsyth return follow('=', One, Oexc); 847*0d13e2d8SCharles.Forsyth '>' => 848*0d13e2d8SCharles.Forsyth c = getc(); 849*0d13e2d8SCharles.Forsyth if(c == '=') 850*0d13e2d8SCharles.Forsyth return Oge; 851*0d13e2d8SCharles.Forsyth if(c == '>') 852*0d13e2d8SCharles.Forsyth return follow('=', Orshe, Orsh); 853*0d13e2d8SCharles.Forsyth ungetc(c); 854*0d13e2d8SCharles.Forsyth return Ogt; 855*0d13e2d8SCharles.Forsyth '<' => 856*0d13e2d8SCharles.Forsyth c = getc(); 857*0d13e2d8SCharles.Forsyth if(c == '=') 858*0d13e2d8SCharles.Forsyth return Ole; 859*0d13e2d8SCharles.Forsyth if(c == '<') 860*0d13e2d8SCharles.Forsyth return follow('=', Olshe, Olsh); 861*0d13e2d8SCharles.Forsyth if(c == '-') 862*0d13e2d8SCharles.Forsyth return follow('>', Oiff, Oimpby); 863*0d13e2d8SCharles.Forsyth ungetc(c); 864*0d13e2d8SCharles.Forsyth return Olt; 865*0d13e2d8SCharles.Forsyth '(' => 866*0d13e2d8SCharles.Forsyth return Olbr; 867*0d13e2d8SCharles.Forsyth ')' => 868*0d13e2d8SCharles.Forsyth return Orbr; 869*0d13e2d8SCharles.Forsyth '{' => 870*0d13e2d8SCharles.Forsyth return Olcbr; 871*0d13e2d8SCharles.Forsyth '}' => 872*0d13e2d8SCharles.Forsyth return Orcbr; 873*0d13e2d8SCharles.Forsyth '~' => 874*0d13e2d8SCharles.Forsyth return Ocom; 875*0d13e2d8SCharles.Forsyth '.' => 876*0d13e2d8SCharles.Forsyth ungetc(c); 877*0d13e2d8SCharles.Forsyth return lexnum(); 878*0d13e2d8SCharles.Forsyth ',' => 879*0d13e2d8SCharles.Forsyth return Ocomma; 880*0d13e2d8SCharles.Forsyth '?' => 881*0d13e2d8SCharles.Forsyth return Oquest; 882*0d13e2d8SCharles.Forsyth ':' => 883*0d13e2d8SCharles.Forsyth return follow('=', Odas, Ocolon); 884*0d13e2d8SCharles.Forsyth ';' => 885*0d13e2d8SCharles.Forsyth return Oscolon; 886*0d13e2d8SCharles.Forsyth '↑' => 887*0d13e2d8SCharles.Forsyth return Onand; 888*0d13e2d8SCharles.Forsyth '↓' => 889*0d13e2d8SCharles.Forsyth return Onor; 890*0d13e2d8SCharles.Forsyth '∞' => 891*0d13e2d8SCharles.Forsyth lexval = Infinity; 892*0d13e2d8SCharles.Forsyth return Onum; 893*0d13e2d8SCharles.Forsyth * => 894*0d13e2d8SCharles.Forsyth error(nil, sys->sprint("bad character %c", c)); 895*0d13e2d8SCharles.Forsyth } 896*0d13e2d8SCharles.Forsyth } 897*0d13e2d8SCharles.Forsyth} 898*0d13e2d8SCharles.Forsyth 899*0d13e2d8SCharles.Forsythunlex(t: int) 900*0d13e2d8SCharles.Forsyth{ 901*0d13e2d8SCharles.Forsyth lexes--; 902*0d13e2d8SCharles.Forsyth buft = t; 903*0d13e2d8SCharles.Forsyth if(t == Onl) 904*0d13e2d8SCharles.Forsyth lineno--; 905*0d13e2d8SCharles.Forsyth} 906*0d13e2d8SCharles.Forsyth 907*0d13e2d8SCharles.Forsythmustbe(t: int) 908*0d13e2d8SCharles.Forsyth{ 909*0d13e2d8SCharles.Forsyth nt := lex(); 910*0d13e2d8SCharles.Forsyth if(nt != t) 911*0d13e2d8SCharles.Forsyth error(nil, sys->sprint("expected %s not %s", opstring(t), opstring(nt))); 912*0d13e2d8SCharles.Forsyth} 913*0d13e2d8SCharles.Forsyth 914*0d13e2d8SCharles.Forsythconsume(t: int) 915*0d13e2d8SCharles.Forsyth{ 916*0d13e2d8SCharles.Forsyth nt := lex(); 917*0d13e2d8SCharles.Forsyth if(nt != t) 918*0d13e2d8SCharles.Forsyth unlex(nt); 919*0d13e2d8SCharles.Forsyth} 920*0d13e2d8SCharles.Forsyth 921*0d13e2d8SCharles.Forsythelex(): int 922*0d13e2d8SCharles.Forsyth{ 923*0d13e2d8SCharles.Forsyth t := lex(); 924*0d13e2d8SCharles.Forsyth if(binary(t)) 925*0d13e2d8SCharles.Forsyth return t; 926*0d13e2d8SCharles.Forsyth if(hexp(t)){ 927*0d13e2d8SCharles.Forsyth unlex(t); 928*0d13e2d8SCharles.Forsyth return Oscomma; 929*0d13e2d8SCharles.Forsyth } 930*0d13e2d8SCharles.Forsyth return t; 931*0d13e2d8SCharles.Forsyth} 932*0d13e2d8SCharles.Forsyth 933*0d13e2d8SCharles.Forsythhexp(o: int): int 934*0d13e2d8SCharles.Forsyth{ 935*0d13e2d8SCharles.Forsyth return preunary(o) || o == Olbr || atom(o); 936*0d13e2d8SCharles.Forsyth} 937*0d13e2d8SCharles.Forsyth 938*0d13e2d8SCharles.Forsythatom(o: int): int 939*0d13e2d8SCharles.Forsyth{ 940*0d13e2d8SCharles.Forsyth return o >= Ostring && o <= Olfun; 941*0d13e2d8SCharles.Forsyth} 942*0d13e2d8SCharles.Forsyth 943*0d13e2d8SCharles.Forsythasop(o: int): int 944*0d13e2d8SCharles.Forsyth{ 945*0d13e2d8SCharles.Forsyth return o == Oas || o == Odas || o >= Oadde && o <= Orshe || o >= Oinc && o <= Opostdec; 946*0d13e2d8SCharles.Forsyth} 947*0d13e2d8SCharles.Forsyth 948*0d13e2d8SCharles.Forsythpreunary(o: int): int 949*0d13e2d8SCharles.Forsyth{ 950*0d13e2d8SCharles.Forsyth return ops[o]&Preunary; 951*0d13e2d8SCharles.Forsyth} 952*0d13e2d8SCharles.Forsyth 953*0d13e2d8SCharles.Forsythpostunary(o: int): int 954*0d13e2d8SCharles.Forsyth{ 955*0d13e2d8SCharles.Forsyth return ops[o]&Postunary; 956*0d13e2d8SCharles.Forsyth} 957*0d13e2d8SCharles.Forsyth 958*0d13e2d8SCharles.Forsythbinary(o: int): int 959*0d13e2d8SCharles.Forsyth{ 960*0d13e2d8SCharles.Forsyth return ops[o]&Binary; 961*0d13e2d8SCharles.Forsyth} 962*0d13e2d8SCharles.Forsyth 963*0d13e2d8SCharles.Forsythprec(o: int): int 964*0d13e2d8SCharles.Forsyth{ 965*0d13e2d8SCharles.Forsyth return ops[o]&Prec; 966*0d13e2d8SCharles.Forsyth} 967*0d13e2d8SCharles.Forsyth 968*0d13e2d8SCharles.Forsythassoc(o: int): int 969*0d13e2d8SCharles.Forsyth{ 970*0d13e2d8SCharles.Forsyth return ops[o]&Assoc; 971*0d13e2d8SCharles.Forsyth} 972*0d13e2d8SCharles.Forsyth 973*0d13e2d8SCharles.Forsythrassoc(o: int): int 974*0d13e2d8SCharles.Forsyth{ 975*0d13e2d8SCharles.Forsyth return ops[o]&Rassoc; 976*0d13e2d8SCharles.Forsyth} 977*0d13e2d8SCharles.Forsyth 978*0d13e2d8SCharles.Forsythpreop(o: int): int 979*0d13e2d8SCharles.Forsyth{ 980*0d13e2d8SCharles.Forsyth case(o){ 981*0d13e2d8SCharles.Forsyth Oadd => return Oplus; 982*0d13e2d8SCharles.Forsyth Osub => return Ominus; 983*0d13e2d8SCharles.Forsyth Oinc => return Opreinc; 984*0d13e2d8SCharles.Forsyth Odec => return Opredec; 985*0d13e2d8SCharles.Forsyth Oexc => return Onot; 986*0d13e2d8SCharles.Forsyth } 987*0d13e2d8SCharles.Forsyth return o; 988*0d13e2d8SCharles.Forsyth} 989*0d13e2d8SCharles.Forsyth 990*0d13e2d8SCharles.Forsythpostop(o: int): int 991*0d13e2d8SCharles.Forsyth{ 992*0d13e2d8SCharles.Forsyth case(o){ 993*0d13e2d8SCharles.Forsyth Oinc => return Opostinc; 994*0d13e2d8SCharles.Forsyth Odec => return Opostdec; 995*0d13e2d8SCharles.Forsyth Oexc => return Ofact; 996*0d13e2d8SCharles.Forsyth } 997*0d13e2d8SCharles.Forsyth return o; 998*0d13e2d8SCharles.Forsyth} 999*0d13e2d8SCharles.Forsyth 1000*0d13e2d8SCharles.Forsythprtree(p: ref Node, in: int) 1001*0d13e2d8SCharles.Forsyth{ 1002*0d13e2d8SCharles.Forsyth if(p == nil) 1003*0d13e2d8SCharles.Forsyth return; 1004*0d13e2d8SCharles.Forsyth for(i := 0; i < in; i++) 1005*0d13e2d8SCharles.Forsyth sys->print(" "); 1006*0d13e2d8SCharles.Forsyth sys->print("%s ", opstring(p.op)); 1007*0d13e2d8SCharles.Forsyth case(p.op){ 1008*0d13e2d8SCharles.Forsyth Ostring => 1009*0d13e2d8SCharles.Forsyth sys->print("%s", p.str); 1010*0d13e2d8SCharles.Forsyth Onum => 1011*0d13e2d8SCharles.Forsyth sys->print("%g", p.val); 1012*0d13e2d8SCharles.Forsyth Ocon or 1013*0d13e2d8SCharles.Forsyth Ovar => 1014*0d13e2d8SCharles.Forsyth sys->print("%s(%g)", p.dec.sym.name, p.dec.val); 1015*0d13e2d8SCharles.Forsyth Ofun or 1016*0d13e2d8SCharles.Forsyth Olfun => 1017*0d13e2d8SCharles.Forsyth sys->print("%s", p.dec.sym.name); 1018*0d13e2d8SCharles.Forsyth } 1019*0d13e2d8SCharles.Forsyth sys->print("\n"); 1020*0d13e2d8SCharles.Forsyth # sys->print(" - %d\n", p.src); 1021*0d13e2d8SCharles.Forsyth prtree(p.left, in+1); 1022*0d13e2d8SCharles.Forsyth prtree(p.right, in+1); 1023*0d13e2d8SCharles.Forsyth} 1024*0d13e2d8SCharles.Forsyth 1025*0d13e2d8SCharles.Forsythtree(o: int, l: ref Node, r: ref Node): ref Node 1026*0d13e2d8SCharles.Forsyth{ 1027*0d13e2d8SCharles.Forsyth p := ref Node; 1028*0d13e2d8SCharles.Forsyth p.op = o; 1029*0d13e2d8SCharles.Forsyth p.left = l; 1030*0d13e2d8SCharles.Forsyth p.right = r; 1031*0d13e2d8SCharles.Forsyth p.src = lineno; 1032*0d13e2d8SCharles.Forsyth if(asop(o)){ 1033*0d13e2d8SCharles.Forsyth if(o >= Oadde && o <= Orshe){ 1034*0d13e2d8SCharles.Forsyth p = tree(Oas, l, p); 1035*0d13e2d8SCharles.Forsyth p.right.op += Oadd-Oadde; 1036*0d13e2d8SCharles.Forsyth } 1037*0d13e2d8SCharles.Forsyth } 1038*0d13e2d8SCharles.Forsyth return p; 1039*0d13e2d8SCharles.Forsyth} 1040*0d13e2d8SCharles.Forsyth 1041*0d13e2d8SCharles.Forsythitree(n: int): ref Node 1042*0d13e2d8SCharles.Forsyth{ 1043*0d13e2d8SCharles.Forsyth return vtree(real n); 1044*0d13e2d8SCharles.Forsyth} 1045*0d13e2d8SCharles.Forsyth 1046*0d13e2d8SCharles.Forsythvtree(v: real): ref Node 1047*0d13e2d8SCharles.Forsyth{ 1048*0d13e2d8SCharles.Forsyth n := tree(Onum, nil, nil); 1049*0d13e2d8SCharles.Forsyth n.val = v; 1050*0d13e2d8SCharles.Forsyth return n; 1051*0d13e2d8SCharles.Forsyth} 1052*0d13e2d8SCharles.Forsyth 1053*0d13e2d8SCharles.Forsythltree(s: string, a: ref Node): ref Node 1054*0d13e2d8SCharles.Forsyth{ 1055*0d13e2d8SCharles.Forsyth n := tree(Olfun, a, nil); 1056*0d13e2d8SCharles.Forsyth n.dec = lookup(s).dec; 1057*0d13e2d8SCharles.Forsyth return n; 1058*0d13e2d8SCharles.Forsyth} 1059*0d13e2d8SCharles.Forsyth 1060*0d13e2d8SCharles.Forsythptree(n: ref Node, p: real): ref Node 1061*0d13e2d8SCharles.Forsyth{ 1062*0d13e2d8SCharles.Forsyth if(isinteger(p)){ 1063*0d13e2d8SCharles.Forsyth i := int p; 1064*0d13e2d8SCharles.Forsyth if(i == 0) 1065*0d13e2d8SCharles.Forsyth return itree(1); 1066*0d13e2d8SCharles.Forsyth if(i == 1) 1067*0d13e2d8SCharles.Forsyth return n; 1068*0d13e2d8SCharles.Forsyth if(i == -1) 1069*0d13e2d8SCharles.Forsyth return tree(Oinv, n, nil); 1070*0d13e2d8SCharles.Forsyth if(i < 0) 1071*0d13e2d8SCharles.Forsyth return tree(Oinv, tree(Oexp, n, itree(-i)), nil); 1072*0d13e2d8SCharles.Forsyth } 1073*0d13e2d8SCharles.Forsyth return tree(Oexp, n, vtree(p)); 1074*0d13e2d8SCharles.Forsyth} 1075*0d13e2d8SCharles.Forsyth 1076*0d13e2d8SCharles.Forsythiscon(n: ref Node): int 1077*0d13e2d8SCharles.Forsyth{ 1078*0d13e2d8SCharles.Forsyth return n.op == Onum || n.op == Ocon; 1079*0d13e2d8SCharles.Forsyth} 1080*0d13e2d8SCharles.Forsyth 1081*0d13e2d8SCharles.Forsythiszero(n: ref Node): int 1082*0d13e2d8SCharles.Forsyth{ 1083*0d13e2d8SCharles.Forsyth return iscon(n) && eval(n) == 0.0; 1084*0d13e2d8SCharles.Forsyth} 1085*0d13e2d8SCharles.Forsyth 1086*0d13e2d8SCharles.Forsythisone(n: ref Node): int 1087*0d13e2d8SCharles.Forsyth{ 1088*0d13e2d8SCharles.Forsyth return iscon(n) && eval(n) == 1.0; 1089*0d13e2d8SCharles.Forsyth} 1090*0d13e2d8SCharles.Forsyth 1091*0d13e2d8SCharles.Forsythisnan(n: ref Node): int 1092*0d13e2d8SCharles.Forsyth{ 1093*0d13e2d8SCharles.Forsyth return iscon(n) && maths->isnan(eval(n)); 1094*0d13e2d8SCharles.Forsyth} 1095*0d13e2d8SCharles.Forsyth 1096*0d13e2d8SCharles.Forsythisinf(n: ref Node): int 1097*0d13e2d8SCharles.Forsyth{ 1098*0d13e2d8SCharles.Forsyth return iscon(n) && (v := eval(n)) == Infinity || v == -Infinity; 1099*0d13e2d8SCharles.Forsyth} 1100*0d13e2d8SCharles.Forsyth 1101*0d13e2d8SCharles.Forsythstat(scope: int): ref Node 1102*0d13e2d8SCharles.Forsyth{ 1103*0d13e2d8SCharles.Forsyth e1, e2, e3, e4: ref Node; 1104*0d13e2d8SCharles.Forsyth 1105*0d13e2d8SCharles.Forsyth consume(Onl); 1106*0d13e2d8SCharles.Forsyth t := lex(); 1107*0d13e2d8SCharles.Forsyth case(t){ 1108*0d13e2d8SCharles.Forsyth Olcbr => 1109*0d13e2d8SCharles.Forsyth if(scope) 1110*0d13e2d8SCharles.Forsyth pushscope(); 1111*0d13e2d8SCharles.Forsyth for(;;){ 1112*0d13e2d8SCharles.Forsyth e2 = stat(1); 1113*0d13e2d8SCharles.Forsyth if(e1 == nil) 1114*0d13e2d8SCharles.Forsyth e1 = e2; 1115*0d13e2d8SCharles.Forsyth else 1116*0d13e2d8SCharles.Forsyth e1 = tree(Ocomma, e1, e2); 1117*0d13e2d8SCharles.Forsyth consume(Onl); 1118*0d13e2d8SCharles.Forsyth t = lex(); 1119*0d13e2d8SCharles.Forsyth if(t == Oeof) 1120*0d13e2d8SCharles.Forsyth raise Eeof; 1121*0d13e2d8SCharles.Forsyth if(t == Orcbr) 1122*0d13e2d8SCharles.Forsyth break; 1123*0d13e2d8SCharles.Forsyth unlex(t); 1124*0d13e2d8SCharles.Forsyth } 1125*0d13e2d8SCharles.Forsyth if(scope) 1126*0d13e2d8SCharles.Forsyth popscope(); 1127*0d13e2d8SCharles.Forsyth return e1; 1128*0d13e2d8SCharles.Forsyth Oprint or 1129*0d13e2d8SCharles.Forsyth Oread or 1130*0d13e2d8SCharles.Forsyth Oret => 1131*0d13e2d8SCharles.Forsyth if(t == Oret && !infn) 1132*0d13e2d8SCharles.Forsyth error(nil, "return not in fn"); 1133*0d13e2d8SCharles.Forsyth e1= tree(t, expr(0, 1), nil); 1134*0d13e2d8SCharles.Forsyth consume(Oscolon); 1135*0d13e2d8SCharles.Forsyth if(t == Oread) 1136*0d13e2d8SCharles.Forsyth allvar(e1.left); 1137*0d13e2d8SCharles.Forsyth return e1; 1138*0d13e2d8SCharles.Forsyth Oif => 1139*0d13e2d8SCharles.Forsyth # mustbe(Olbr); 1140*0d13e2d8SCharles.Forsyth e1 = expr(0, 1); 1141*0d13e2d8SCharles.Forsyth # mustbe(Orbr); 1142*0d13e2d8SCharles.Forsyth e2 = stat(1); 1143*0d13e2d8SCharles.Forsyth e3 = nil; 1144*0d13e2d8SCharles.Forsyth consume(Onl); 1145*0d13e2d8SCharles.Forsyth t = lex(); 1146*0d13e2d8SCharles.Forsyth if(t == Oelse) 1147*0d13e2d8SCharles.Forsyth e3 = stat(1); 1148*0d13e2d8SCharles.Forsyth else 1149*0d13e2d8SCharles.Forsyth unlex(t); 1150*0d13e2d8SCharles.Forsyth return tree(Oif, e1, tree(Ocomma, e2, e3)); 1151*0d13e2d8SCharles.Forsyth Ofor => 1152*0d13e2d8SCharles.Forsyth inloop++; 1153*0d13e2d8SCharles.Forsyth mustbe(Olbr); 1154*0d13e2d8SCharles.Forsyth e1 = expr(0, 1); 1155*0d13e2d8SCharles.Forsyth mustbe(Oscolon); 1156*0d13e2d8SCharles.Forsyth e2 = expr(0, 1); 1157*0d13e2d8SCharles.Forsyth mustbe(Oscolon); 1158*0d13e2d8SCharles.Forsyth e3 = expr(0, 1); 1159*0d13e2d8SCharles.Forsyth mustbe(Orbr); 1160*0d13e2d8SCharles.Forsyth e4 = stat(1); 1161*0d13e2d8SCharles.Forsyth inloop--; 1162*0d13e2d8SCharles.Forsyth return tree(Ocomma, e1, tree(Ofor, e2, tree(Ocomma, e4, e3))); 1163*0d13e2d8SCharles.Forsyth Owhile => 1164*0d13e2d8SCharles.Forsyth inloop++; 1165*0d13e2d8SCharles.Forsyth # mustbe(Olbr); 1166*0d13e2d8SCharles.Forsyth e1 = expr(0, 1); 1167*0d13e2d8SCharles.Forsyth # mustbe(Orbr); 1168*0d13e2d8SCharles.Forsyth e2 = stat(1); 1169*0d13e2d8SCharles.Forsyth inloop--; 1170*0d13e2d8SCharles.Forsyth return tree(Ofor, e1, tree(Ocomma, e2, nil)); 1171*0d13e2d8SCharles.Forsyth Odo => 1172*0d13e2d8SCharles.Forsyth inloop++; 1173*0d13e2d8SCharles.Forsyth e1 = stat(1); 1174*0d13e2d8SCharles.Forsyth consume(Onl); 1175*0d13e2d8SCharles.Forsyth mustbe(Owhile); 1176*0d13e2d8SCharles.Forsyth # mustbe(Olbr); 1177*0d13e2d8SCharles.Forsyth e2 = expr(0, 1); 1178*0d13e2d8SCharles.Forsyth # mustbe(Orbr); 1179*0d13e2d8SCharles.Forsyth consume(Oscolon); 1180*0d13e2d8SCharles.Forsyth inloop--; 1181*0d13e2d8SCharles.Forsyth return tree(Odo, e1, e2); 1182*0d13e2d8SCharles.Forsyth Obreak or 1183*0d13e2d8SCharles.Forsyth Ocont or 1184*0d13e2d8SCharles.Forsyth Oexit => 1185*0d13e2d8SCharles.Forsyth if((t == Obreak || t == Ocont) && !inloop) 1186*0d13e2d8SCharles.Forsyth error(nil, "break/continue not in loop"); 1187*0d13e2d8SCharles.Forsyth consume(Oscolon); 1188*0d13e2d8SCharles.Forsyth return tree(t, nil, nil); 1189*0d13e2d8SCharles.Forsyth Ofn => 1190*0d13e2d8SCharles.Forsyth if(infn) 1191*0d13e2d8SCharles.Forsyth error(nil, "nested functions not allowed"); 1192*0d13e2d8SCharles.Forsyth infn++; 1193*0d13e2d8SCharles.Forsyth mustbe(Oident); 1194*0d13e2d8SCharles.Forsyth s := lexsym; 1195*0d13e2d8SCharles.Forsyth d := mkdec(s, Ofun, 1); 1196*0d13e2d8SCharles.Forsyth d.code = tree(Ofn, nil, nil); 1197*0d13e2d8SCharles.Forsyth pushscope(); 1198*0d13e2d8SCharles.Forsyth (d.na, d.code.left) = args(0); 1199*0d13e2d8SCharles.Forsyth allvar(d.code.left); 1200*0d13e2d8SCharles.Forsyth pushparams(d.code.left); 1201*0d13e2d8SCharles.Forsyth d.code.right = stat(0); 1202*0d13e2d8SCharles.Forsyth popscope(); 1203*0d13e2d8SCharles.Forsyth infn--; 1204*0d13e2d8SCharles.Forsyth return d.code; 1205*0d13e2d8SCharles.Forsyth Oinclude => 1206*0d13e2d8SCharles.Forsyth e1 = expr(0, 0); 1207*0d13e2d8SCharles.Forsyth if(e1.op != Ostring) 1208*0d13e2d8SCharles.Forsyth error(nil, "bad include file"); 1209*0d13e2d8SCharles.Forsyth consume(Oscolon); 1210*0d13e2d8SCharles.Forsyth doinclude(e1.str); 1211*0d13e2d8SCharles.Forsyth return nil; 1212*0d13e2d8SCharles.Forsyth * => 1213*0d13e2d8SCharles.Forsyth unlex(t); 1214*0d13e2d8SCharles.Forsyth e1 = expr(0, 1); 1215*0d13e2d8SCharles.Forsyth consume(Oscolon); 1216*0d13e2d8SCharles.Forsyth if(debug) 1217*0d13e2d8SCharles.Forsyth prnode(e1); 1218*0d13e2d8SCharles.Forsyth return e1; 1219*0d13e2d8SCharles.Forsyth } 1220*0d13e2d8SCharles.Forsyth return nil; 1221*0d13e2d8SCharles.Forsyth} 1222*0d13e2d8SCharles.Forsyth 1223*0d13e2d8SCharles.Forsythckstat(n: ref Node, parop: int, pr: int) 1224*0d13e2d8SCharles.Forsyth{ 1225*0d13e2d8SCharles.Forsyth if(n == nil) 1226*0d13e2d8SCharles.Forsyth return; 1227*0d13e2d8SCharles.Forsyth pr |= n.op == Oprint; 1228*0d13e2d8SCharles.Forsyth ckstat(n.left, n.op, pr); 1229*0d13e2d8SCharles.Forsyth ckstat(n.right, n.op, pr); 1230*0d13e2d8SCharles.Forsyth case(n.op){ 1231*0d13e2d8SCharles.Forsyth Ostring => 1232*0d13e2d8SCharles.Forsyth if(!pr || parop != Oprint && parop != Ocomma) 1233*0d13e2d8SCharles.Forsyth error(n, "illegal string operation"); 1234*0d13e2d8SCharles.Forsyth } 1235*0d13e2d8SCharles.Forsyth} 1236*0d13e2d8SCharles.Forsyth 1237*0d13e2d8SCharles.Forsythpexp(e: ref Node): int 1238*0d13e2d8SCharles.Forsyth{ 1239*0d13e2d8SCharles.Forsyth if(e == nil) 1240*0d13e2d8SCharles.Forsyth return 0; 1241*0d13e2d8SCharles.Forsyth if(e.op == Ocomma) 1242*0d13e2d8SCharles.Forsyth return pexp(e.right); 1243*0d13e2d8SCharles.Forsyth return e.op >= Ostring && e.op <= Oiff && !asop(e.op); 1244*0d13e2d8SCharles.Forsyth} 1245*0d13e2d8SCharles.Forsyth 1246*0d13e2d8SCharles.Forsythexpr(p: int, zok: int): ref Node 1247*0d13e2d8SCharles.Forsyth{ 1248*0d13e2d8SCharles.Forsyth n := exp(p, zok); 1249*0d13e2d8SCharles.Forsyth ckexp(n, Onothing); 1250*0d13e2d8SCharles.Forsyth return n; 1251*0d13e2d8SCharles.Forsyth} 1252*0d13e2d8SCharles.Forsyth 1253*0d13e2d8SCharles.Forsythexp(p: int, zok: int): ref Node 1254*0d13e2d8SCharles.Forsyth{ 1255*0d13e2d8SCharles.Forsyth l := prim(zok); 1256*0d13e2d8SCharles.Forsyth if(l == nil) 1257*0d13e2d8SCharles.Forsyth return nil; 1258*0d13e2d8SCharles.Forsyth while(binary(t := elex()) && (o := prec(t)) >= p){ 1259*0d13e2d8SCharles.Forsyth if(rassoc(t)) 1260*0d13e2d8SCharles.Forsyth r := exp(o, 0); 1261*0d13e2d8SCharles.Forsyth else 1262*0d13e2d8SCharles.Forsyth r = exp(o+1, 0); 1263*0d13e2d8SCharles.Forsyth if(t == Oscomma) 1264*0d13e2d8SCharles.Forsyth t = Ocomma; 1265*0d13e2d8SCharles.Forsyth l = tree(t, l, r); 1266*0d13e2d8SCharles.Forsyth } 1267*0d13e2d8SCharles.Forsyth if(t != Oscomma) 1268*0d13e2d8SCharles.Forsyth unlex(t); 1269*0d13e2d8SCharles.Forsyth return l; 1270*0d13e2d8SCharles.Forsyth} 1271*0d13e2d8SCharles.Forsyth 1272*0d13e2d8SCharles.Forsythprim(zok: int): ref Node 1273*0d13e2d8SCharles.Forsyth{ 1274*0d13e2d8SCharles.Forsyth p: ref Node; 1275*0d13e2d8SCharles.Forsyth na: int; 1276*0d13e2d8SCharles.Forsyth 1277*0d13e2d8SCharles.Forsyth t := lex(); 1278*0d13e2d8SCharles.Forsyth if(preunary(t)){ 1279*0d13e2d8SCharles.Forsyth t = preop(t); 1280*0d13e2d8SCharles.Forsyth return tree(t, exp(prec(t), 0), nil); 1281*0d13e2d8SCharles.Forsyth } 1282*0d13e2d8SCharles.Forsyth case(t){ 1283*0d13e2d8SCharles.Forsyth Olbr => 1284*0d13e2d8SCharles.Forsyth p = exp(0, zok); 1285*0d13e2d8SCharles.Forsyth mustbe(Orbr); 1286*0d13e2d8SCharles.Forsyth Ostring => 1287*0d13e2d8SCharles.Forsyth p = tree(t, nil, nil); 1288*0d13e2d8SCharles.Forsyth p.str = lexstr; 1289*0d13e2d8SCharles.Forsyth Onum => 1290*0d13e2d8SCharles.Forsyth p = tree(t, nil ,nil); 1291*0d13e2d8SCharles.Forsyth p.val = lexval; 1292*0d13e2d8SCharles.Forsyth Oident => 1293*0d13e2d8SCharles.Forsyth s := lexsym; 1294*0d13e2d8SCharles.Forsyth d := s.dec; 1295*0d13e2d8SCharles.Forsyth if(d == nil) 1296*0d13e2d8SCharles.Forsyth d = mkdec(s, Ovar, 0); 1297*0d13e2d8SCharles.Forsyth case(t = d.kind){ 1298*0d13e2d8SCharles.Forsyth Ocon or 1299*0d13e2d8SCharles.Forsyth Ovar => 1300*0d13e2d8SCharles.Forsyth p = tree(t, nil, nil); 1301*0d13e2d8SCharles.Forsyth p.dec = d; 1302*0d13e2d8SCharles.Forsyth Ofun or 1303*0d13e2d8SCharles.Forsyth Olfun => 1304*0d13e2d8SCharles.Forsyth p = tree(t, nil, nil); 1305*0d13e2d8SCharles.Forsyth p.dec = d; 1306*0d13e2d8SCharles.Forsyth (na, p.left) = args(prec(t)); 1307*0d13e2d8SCharles.Forsyth if(!(t == Olfun && d.val == real Osolve && na == 2)) 1308*0d13e2d8SCharles.Forsyth if(na != d.na) 1309*0d13e2d8SCharles.Forsyth error(p, "wrong number of arguments"); 1310*0d13e2d8SCharles.Forsyth if(t == Olfun){ 1311*0d13e2d8SCharles.Forsyth case(int d.val){ 1312*0d13e2d8SCharles.Forsyth Osigma or 1313*0d13e2d8SCharles.Forsyth Opi or 1314*0d13e2d8SCharles.Forsyth Ocfrac or 1315*0d13e2d8SCharles.Forsyth Ointeg => 1316*0d13e2d8SCharles.Forsyth if((op := p.left.left.left.op) != Oas && op != Odas) 1317*0d13e2d8SCharles.Forsyth error(p.left, "expression not an assignment"); 1318*0d13e2d8SCharles.Forsyth Oderiv => 1319*0d13e2d8SCharles.Forsyth if((op := p.left.left.op) != Oas && op != Odas) 1320*0d13e2d8SCharles.Forsyth error(p.left, "expression not an assignment"); 1321*0d13e2d8SCharles.Forsyth } 1322*0d13e2d8SCharles.Forsyth } 1323*0d13e2d8SCharles.Forsyth } 1324*0d13e2d8SCharles.Forsyth * => 1325*0d13e2d8SCharles.Forsyth unlex(t); 1326*0d13e2d8SCharles.Forsyth if(!zok) 1327*0d13e2d8SCharles.Forsyth error(nil, "missing expression"); 1328*0d13e2d8SCharles.Forsyth return nil; 1329*0d13e2d8SCharles.Forsyth } 1330*0d13e2d8SCharles.Forsyth while(postunary(t = lex())){ 1331*0d13e2d8SCharles.Forsyth t = postop(t); 1332*0d13e2d8SCharles.Forsyth p = tree(t, p, nil); 1333*0d13e2d8SCharles.Forsyth } 1334*0d13e2d8SCharles.Forsyth unlex(t); 1335*0d13e2d8SCharles.Forsyth return p; 1336*0d13e2d8SCharles.Forsyth} 1337*0d13e2d8SCharles.Forsyth 1338*0d13e2d8SCharles.Forsythckexp(n: ref Node, parop: int) 1339*0d13e2d8SCharles.Forsyth{ 1340*0d13e2d8SCharles.Forsyth if(n == nil) 1341*0d13e2d8SCharles.Forsyth return; 1342*0d13e2d8SCharles.Forsyth o := n.op; 1343*0d13e2d8SCharles.Forsyth l := n.left; 1344*0d13e2d8SCharles.Forsyth r := n.right; 1345*0d13e2d8SCharles.Forsyth if(asop(o)) 1346*0d13e2d8SCharles.Forsyth var(l); 1347*0d13e2d8SCharles.Forsyth case(o){ 1348*0d13e2d8SCharles.Forsyth Ovar => 1349*0d13e2d8SCharles.Forsyth s := n.dec.sym; 1350*0d13e2d8SCharles.Forsyth d := s.dec; 1351*0d13e2d8SCharles.Forsyth if(d == nil){ 1352*0d13e2d8SCharles.Forsyth if(strict) 1353*0d13e2d8SCharles.Forsyth error(n, sys->sprint("%s undefined", s.name)); 1354*0d13e2d8SCharles.Forsyth d = mkdec(s, Ovar, 1); 1355*0d13e2d8SCharles.Forsyth } 1356*0d13e2d8SCharles.Forsyth n.dec = d; 1357*0d13e2d8SCharles.Forsyth Odas => 1358*0d13e2d8SCharles.Forsyth ckexp(r, o); 1359*0d13e2d8SCharles.Forsyth l.dec = mkdec(l.dec.sym, Ovar, 1); 1360*0d13e2d8SCharles.Forsyth * => 1361*0d13e2d8SCharles.Forsyth ckexp(l, o); 1362*0d13e2d8SCharles.Forsyth ckexp(r, o); 1363*0d13e2d8SCharles.Forsyth if(o == Oquest && r.op != Ocolon) 1364*0d13e2d8SCharles.Forsyth error(n, "bad '?' operator"); 1365*0d13e2d8SCharles.Forsyth if(o == Ocolon && parop != Oquest) 1366*0d13e2d8SCharles.Forsyth error(n, "bad ':' operator"); 1367*0d13e2d8SCharles.Forsyth } 1368*0d13e2d8SCharles.Forsyth} 1369*0d13e2d8SCharles.Forsyth 1370*0d13e2d8SCharles.Forsythcommas(n: ref Node): int 1371*0d13e2d8SCharles.Forsyth{ 1372*0d13e2d8SCharles.Forsyth if(n == nil || n.op == Ofun || n.op == Olfun) 1373*0d13e2d8SCharles.Forsyth return 0; 1374*0d13e2d8SCharles.Forsyth c := commas(n.left)+commas(n.right); 1375*0d13e2d8SCharles.Forsyth if(n.op == Ocomma) 1376*0d13e2d8SCharles.Forsyth c++; 1377*0d13e2d8SCharles.Forsyth return c; 1378*0d13e2d8SCharles.Forsyth} 1379*0d13e2d8SCharles.Forsyth 1380*0d13e2d8SCharles.Forsythallvar(n: ref Node) 1381*0d13e2d8SCharles.Forsyth{ 1382*0d13e2d8SCharles.Forsyth if(n == nil) 1383*0d13e2d8SCharles.Forsyth return; 1384*0d13e2d8SCharles.Forsyth if(n.op == Ocomma){ 1385*0d13e2d8SCharles.Forsyth allvar(n.left); 1386*0d13e2d8SCharles.Forsyth allvar(n.right); 1387*0d13e2d8SCharles.Forsyth return; 1388*0d13e2d8SCharles.Forsyth } 1389*0d13e2d8SCharles.Forsyth var(n); 1390*0d13e2d8SCharles.Forsyth} 1391*0d13e2d8SCharles.Forsyth 1392*0d13e2d8SCharles.Forsythargs(p: int): (int, ref Node) 1393*0d13e2d8SCharles.Forsyth{ 1394*0d13e2d8SCharles.Forsyth if(!p) 1395*0d13e2d8SCharles.Forsyth mustbe(Olbr); 1396*0d13e2d8SCharles.Forsyth a := exp(p, 1); 1397*0d13e2d8SCharles.Forsyth if(!p) 1398*0d13e2d8SCharles.Forsyth mustbe(Orbr); 1399*0d13e2d8SCharles.Forsyth na := 0; 1400*0d13e2d8SCharles.Forsyth if(a != nil) 1401*0d13e2d8SCharles.Forsyth na = commas(a)+1; 1402*0d13e2d8SCharles.Forsyth return (na, a); 1403*0d13e2d8SCharles.Forsyth} 1404*0d13e2d8SCharles.Forsyth 1405*0d13e2d8SCharles.Forsythhash(s: string): int 1406*0d13e2d8SCharles.Forsyth{ 1407*0d13e2d8SCharles.Forsyth l := len s; 1408*0d13e2d8SCharles.Forsyth h := 4104; 1409*0d13e2d8SCharles.Forsyth for(i := 0; i < l; i++) 1410*0d13e2d8SCharles.Forsyth h = 1729*h ^ s[i]; 1411*0d13e2d8SCharles.Forsyth if(h < 0) 1412*0d13e2d8SCharles.Forsyth h = -h; 1413*0d13e2d8SCharles.Forsyth return h&(Hash-1); 1414*0d13e2d8SCharles.Forsyth} 1415*0d13e2d8SCharles.Forsyth 1416*0d13e2d8SCharles.Forsythenter(sp: string, k: int): ref Sym 1417*0d13e2d8SCharles.Forsyth{ 1418*0d13e2d8SCharles.Forsyth for(s := syms[hash(sp)]; s != nil; s = s.next){ 1419*0d13e2d8SCharles.Forsyth if(sp == s.name) 1420*0d13e2d8SCharles.Forsyth return s; 1421*0d13e2d8SCharles.Forsyth } 1422*0d13e2d8SCharles.Forsyth s = ref Sym; 1423*0d13e2d8SCharles.Forsyth s.name = sp; 1424*0d13e2d8SCharles.Forsyth s.kind = k; 1425*0d13e2d8SCharles.Forsyth h := hash(sp); 1426*0d13e2d8SCharles.Forsyth s.next = syms[h]; 1427*0d13e2d8SCharles.Forsyth syms[h] = s; 1428*0d13e2d8SCharles.Forsyth return s; 1429*0d13e2d8SCharles.Forsyth} 1430*0d13e2d8SCharles.Forsyth 1431*0d13e2d8SCharles.Forsythlookup(sp: string): ref Sym 1432*0d13e2d8SCharles.Forsyth{ 1433*0d13e2d8SCharles.Forsyth return enter(sp, Oident); 1434*0d13e2d8SCharles.Forsyth} 1435*0d13e2d8SCharles.Forsyth 1436*0d13e2d8SCharles.Forsythmkdec(s: ref Sym, k: int, dec: int): ref Dec 1437*0d13e2d8SCharles.Forsyth{ 1438*0d13e2d8SCharles.Forsyth d := ref Dec; 1439*0d13e2d8SCharles.Forsyth d.kind = k; 1440*0d13e2d8SCharles.Forsyth d.val = 0.0; 1441*0d13e2d8SCharles.Forsyth d.na = 0; 1442*0d13e2d8SCharles.Forsyth d.sym = s; 1443*0d13e2d8SCharles.Forsyth d.scope = 0; 1444*0d13e2d8SCharles.Forsyth if(dec) 1445*0d13e2d8SCharles.Forsyth pushdec(d); 1446*0d13e2d8SCharles.Forsyth return d; 1447*0d13e2d8SCharles.Forsyth} 1448*0d13e2d8SCharles.Forsyth 1449*0d13e2d8SCharles.Forsythadddec(sp: string, k: int, v: real, n: int): ref Dec 1450*0d13e2d8SCharles.Forsyth{ 1451*0d13e2d8SCharles.Forsyth d := mkdec(enter(sp, Oident), k, 1); 1452*0d13e2d8SCharles.Forsyth d.val = v; 1453*0d13e2d8SCharles.Forsyth d.na = n; 1454*0d13e2d8SCharles.Forsyth return d; 1455*0d13e2d8SCharles.Forsyth} 1456*0d13e2d8SCharles.Forsyth 1457*0d13e2d8SCharles.Forsythscope: int; 1458*0d13e2d8SCharles.Forsythcurscope: ref Dec; 1459*0d13e2d8SCharles.Forsythscopes: list of ref Dec; 1460*0d13e2d8SCharles.Forsyth 1461*0d13e2d8SCharles.Forsythpushscope() 1462*0d13e2d8SCharles.Forsyth{ 1463*0d13e2d8SCharles.Forsyth scope++; 1464*0d13e2d8SCharles.Forsyth scopes = curscope :: scopes; 1465*0d13e2d8SCharles.Forsyth curscope = nil; 1466*0d13e2d8SCharles.Forsyth} 1467*0d13e2d8SCharles.Forsyth 1468*0d13e2d8SCharles.Forsythpopscope() 1469*0d13e2d8SCharles.Forsyth{ 1470*0d13e2d8SCharles.Forsyth popdecs(); 1471*0d13e2d8SCharles.Forsyth curscope = hd scopes; 1472*0d13e2d8SCharles.Forsyth scopes = tl scopes; 1473*0d13e2d8SCharles.Forsyth scope--; 1474*0d13e2d8SCharles.Forsyth} 1475*0d13e2d8SCharles.Forsyth 1476*0d13e2d8SCharles.Forsythpushparams(n: ref Node) 1477*0d13e2d8SCharles.Forsyth{ 1478*0d13e2d8SCharles.Forsyth if(n == nil) 1479*0d13e2d8SCharles.Forsyth return; 1480*0d13e2d8SCharles.Forsyth if(n.op == Ocomma){ 1481*0d13e2d8SCharles.Forsyth pushparams(n.left); 1482*0d13e2d8SCharles.Forsyth pushparams(n.right); 1483*0d13e2d8SCharles.Forsyth return; 1484*0d13e2d8SCharles.Forsyth } 1485*0d13e2d8SCharles.Forsyth n.dec = mkdec(n.dec.sym, Ovar, 1); 1486*0d13e2d8SCharles.Forsyth} 1487*0d13e2d8SCharles.Forsyth 1488*0d13e2d8SCharles.Forsythpushdec(d: ref Dec) 1489*0d13e2d8SCharles.Forsyth{ 1490*0d13e2d8SCharles.Forsyth if(0 && debug) 1491*0d13e2d8SCharles.Forsyth sys->print("dec %s scope %d\n", d.sym.name, scope); 1492*0d13e2d8SCharles.Forsyth d.scope = scope; 1493*0d13e2d8SCharles.Forsyth s := d.sym; 1494*0d13e2d8SCharles.Forsyth if(s.dec != nil && s.dec.scope == scope) 1495*0d13e2d8SCharles.Forsyth error(nil, sys->sprint("redeclaration of %s", s.name)); 1496*0d13e2d8SCharles.Forsyth d.old = s.dec; 1497*0d13e2d8SCharles.Forsyth s.dec = d; 1498*0d13e2d8SCharles.Forsyth d.next = curscope; 1499*0d13e2d8SCharles.Forsyth curscope = d; 1500*0d13e2d8SCharles.Forsyth} 1501*0d13e2d8SCharles.Forsyth 1502*0d13e2d8SCharles.Forsythpopdecs() 1503*0d13e2d8SCharles.Forsyth{ 1504*0d13e2d8SCharles.Forsyth nd: ref Dec; 1505*0d13e2d8SCharles.Forsyth for(d := curscope; d != nil; d = nd){ 1506*0d13e2d8SCharles.Forsyth d.sym.dec = d.old; 1507*0d13e2d8SCharles.Forsyth d.old = nil; 1508*0d13e2d8SCharles.Forsyth nd = d.next; 1509*0d13e2d8SCharles.Forsyth d.next = nil; 1510*0d13e2d8SCharles.Forsyth } 1511*0d13e2d8SCharles.Forsyth curscope = nil; 1512*0d13e2d8SCharles.Forsyth} 1513*0d13e2d8SCharles.Forsyth 1514*0d13e2d8SCharles.Forsythestat(n: ref Node): (int, real) 1515*0d13e2d8SCharles.Forsyth{ 1516*0d13e2d8SCharles.Forsyth k: int; 1517*0d13e2d8SCharles.Forsyth v: real; 1518*0d13e2d8SCharles.Forsyth 1519*0d13e2d8SCharles.Forsyth if(n == nil) 1520*0d13e2d8SCharles.Forsyth return (Onothing, 0.0); 1521*0d13e2d8SCharles.Forsyth l := n.left; 1522*0d13e2d8SCharles.Forsyth r := n.right; 1523*0d13e2d8SCharles.Forsyth case(n.op){ 1524*0d13e2d8SCharles.Forsyth Ocomma => 1525*0d13e2d8SCharles.Forsyth (k, v) = estat(l); 1526*0d13e2d8SCharles.Forsyth if(k == Oexit || k == Oret || k == Obreak || k == Ocont) 1527*0d13e2d8SCharles.Forsyth return (k, v); 1528*0d13e2d8SCharles.Forsyth return estat(r); 1529*0d13e2d8SCharles.Forsyth Oprint => 1530*0d13e2d8SCharles.Forsyth v = print(l); 1531*0d13e2d8SCharles.Forsyth return (Onothing, v); 1532*0d13e2d8SCharles.Forsyth Oread => 1533*0d13e2d8SCharles.Forsyth v = read(l); 1534*0d13e2d8SCharles.Forsyth return (Onothing, v); 1535*0d13e2d8SCharles.Forsyth Obreak or 1536*0d13e2d8SCharles.Forsyth Ocont or 1537*0d13e2d8SCharles.Forsyth Oexit => 1538*0d13e2d8SCharles.Forsyth return (n.op, 0.0); 1539*0d13e2d8SCharles.Forsyth Oret => 1540*0d13e2d8SCharles.Forsyth return (Oret, eval(l)); 1541*0d13e2d8SCharles.Forsyth Oif => 1542*0d13e2d8SCharles.Forsyth v = eval(l); 1543*0d13e2d8SCharles.Forsyth if(int v) 1544*0d13e2d8SCharles.Forsyth return estat(r.left); 1545*0d13e2d8SCharles.Forsyth else if(r.right != nil) 1546*0d13e2d8SCharles.Forsyth return estat(r.right); 1547*0d13e2d8SCharles.Forsyth else 1548*0d13e2d8SCharles.Forsyth return (Onothing, v); 1549*0d13e2d8SCharles.Forsyth Ofor => 1550*0d13e2d8SCharles.Forsyth for(;;){ 1551*0d13e2d8SCharles.Forsyth v = eval(l); 1552*0d13e2d8SCharles.Forsyth if(!int v) 1553*0d13e2d8SCharles.Forsyth break; 1554*0d13e2d8SCharles.Forsyth (k, v) = estat(r.left); 1555*0d13e2d8SCharles.Forsyth if(k == Oexit || k == Oret) 1556*0d13e2d8SCharles.Forsyth return (k, v); 1557*0d13e2d8SCharles.Forsyth if(k == Obreak) 1558*0d13e2d8SCharles.Forsyth break; 1559*0d13e2d8SCharles.Forsyth if(r.right != nil) 1560*0d13e2d8SCharles.Forsyth v = eval(r.right); 1561*0d13e2d8SCharles.Forsyth } 1562*0d13e2d8SCharles.Forsyth return (Onothing, v); 1563*0d13e2d8SCharles.Forsyth Odo => 1564*0d13e2d8SCharles.Forsyth for(;;){ 1565*0d13e2d8SCharles.Forsyth (k, v) = estat(l); 1566*0d13e2d8SCharles.Forsyth if(k == Oexit || k == Oret) 1567*0d13e2d8SCharles.Forsyth return (k, v); 1568*0d13e2d8SCharles.Forsyth if(k == Obreak) 1569*0d13e2d8SCharles.Forsyth break; 1570*0d13e2d8SCharles.Forsyth v = eval(r); 1571*0d13e2d8SCharles.Forsyth if(!int v) 1572*0d13e2d8SCharles.Forsyth break; 1573*0d13e2d8SCharles.Forsyth } 1574*0d13e2d8SCharles.Forsyth return (Onothing, v); 1575*0d13e2d8SCharles.Forsyth * => 1576*0d13e2d8SCharles.Forsyth return (Onothing, eval(n)); 1577*0d13e2d8SCharles.Forsyth } 1578*0d13e2d8SCharles.Forsyth return (Onothing, 0.0); 1579*0d13e2d8SCharles.Forsyth} 1580*0d13e2d8SCharles.Forsyth 1581*0d13e2d8SCharles.Forsytheval(e: ref Node): real 1582*0d13e2d8SCharles.Forsyth{ 1583*0d13e2d8SCharles.Forsyth lv, rv: real; 1584*0d13e2d8SCharles.Forsyth 1585*0d13e2d8SCharles.Forsyth if(e == nil) 1586*0d13e2d8SCharles.Forsyth return 1.0; 1587*0d13e2d8SCharles.Forsyth o := e.op; 1588*0d13e2d8SCharles.Forsyth l := e.left; 1589*0d13e2d8SCharles.Forsyth r := e.right; 1590*0d13e2d8SCharles.Forsyth if(o != Ofun && o != Olfun) 1591*0d13e2d8SCharles.Forsyth lv = eval(l); 1592*0d13e2d8SCharles.Forsyth if(o != Oandand && o != Ooror && o != Oquest) 1593*0d13e2d8SCharles.Forsyth rv = eval(r); 1594*0d13e2d8SCharles.Forsyth case(o){ 1595*0d13e2d8SCharles.Forsyth Ostring => 1596*0d13e2d8SCharles.Forsyth return 0.0; 1597*0d13e2d8SCharles.Forsyth Onum => 1598*0d13e2d8SCharles.Forsyth return e.val; 1599*0d13e2d8SCharles.Forsyth Ocon or 1600*0d13e2d8SCharles.Forsyth Ovar => 1601*0d13e2d8SCharles.Forsyth return e.dec.val; 1602*0d13e2d8SCharles.Forsyth Ofun => 1603*0d13e2d8SCharles.Forsyth return call(e.dec, l); 1604*0d13e2d8SCharles.Forsyth Olfun => 1605*0d13e2d8SCharles.Forsyth return libfun(int e.dec.val, l); 1606*0d13e2d8SCharles.Forsyth Oadd => 1607*0d13e2d8SCharles.Forsyth return lv+rv; 1608*0d13e2d8SCharles.Forsyth Osub => 1609*0d13e2d8SCharles.Forsyth return lv-rv; 1610*0d13e2d8SCharles.Forsyth Omul => 1611*0d13e2d8SCharles.Forsyth return lv*rv; 1612*0d13e2d8SCharles.Forsyth Odiv => 1613*0d13e2d8SCharles.Forsyth return lv/rv; 1614*0d13e2d8SCharles.Forsyth Omod => 1615*0d13e2d8SCharles.Forsyth return real (big lv%big rv); 1616*0d13e2d8SCharles.Forsyth Oidiv => 1617*0d13e2d8SCharles.Forsyth return real (big lv/big rv); 1618*0d13e2d8SCharles.Forsyth Oand => 1619*0d13e2d8SCharles.Forsyth return real (big lv&big rv); 1620*0d13e2d8SCharles.Forsyth Oor => 1621*0d13e2d8SCharles.Forsyth return real (big lv|big rv); 1622*0d13e2d8SCharles.Forsyth Oxor => 1623*0d13e2d8SCharles.Forsyth return real (big lv^big rv); 1624*0d13e2d8SCharles.Forsyth Olsh => 1625*0d13e2d8SCharles.Forsyth return real (big lv<<int rv); 1626*0d13e2d8SCharles.Forsyth Orsh => 1627*0d13e2d8SCharles.Forsyth return real (big lv>>int rv); 1628*0d13e2d8SCharles.Forsyth Oeq => 1629*0d13e2d8SCharles.Forsyth return real (lv == rv); 1630*0d13e2d8SCharles.Forsyth One => 1631*0d13e2d8SCharles.Forsyth return real (lv != rv); 1632*0d13e2d8SCharles.Forsyth Ogt => 1633*0d13e2d8SCharles.Forsyth return real (lv > rv); 1634*0d13e2d8SCharles.Forsyth Olt => 1635*0d13e2d8SCharles.Forsyth return real (lv < rv); 1636*0d13e2d8SCharles.Forsyth Oge => 1637*0d13e2d8SCharles.Forsyth return real (lv >= rv); 1638*0d13e2d8SCharles.Forsyth Ole => 1639*0d13e2d8SCharles.Forsyth return real (lv <= rv); 1640*0d13e2d8SCharles.Forsyth Opreinc => 1641*0d13e2d8SCharles.Forsyth l.dec.val += 1.0; 1642*0d13e2d8SCharles.Forsyth return l.dec.val; 1643*0d13e2d8SCharles.Forsyth Opostinc => 1644*0d13e2d8SCharles.Forsyth l.dec.val += 1.0; 1645*0d13e2d8SCharles.Forsyth return l.dec.val-1.0; 1646*0d13e2d8SCharles.Forsyth Opredec => 1647*0d13e2d8SCharles.Forsyth l.dec.val -= 1.0; 1648*0d13e2d8SCharles.Forsyth return l.dec.val; 1649*0d13e2d8SCharles.Forsyth Opostdec => 1650*0d13e2d8SCharles.Forsyth l.dec.val -= 1.0; 1651*0d13e2d8SCharles.Forsyth return l.dec.val+1.0; 1652*0d13e2d8SCharles.Forsyth Oexp => 1653*0d13e2d8SCharles.Forsyth if(isinteger(rv) && rv >= 0.0) 1654*0d13e2d8SCharles.Forsyth return lv**int rv; 1655*0d13e2d8SCharles.Forsyth return maths->pow(lv, rv); 1656*0d13e2d8SCharles.Forsyth Oandand => 1657*0d13e2d8SCharles.Forsyth if(!int lv) 1658*0d13e2d8SCharles.Forsyth return lv; 1659*0d13e2d8SCharles.Forsyth return eval(r); 1660*0d13e2d8SCharles.Forsyth Ooror => 1661*0d13e2d8SCharles.Forsyth if(int lv) 1662*0d13e2d8SCharles.Forsyth return lv; 1663*0d13e2d8SCharles.Forsyth return eval(r); 1664*0d13e2d8SCharles.Forsyth Onot => 1665*0d13e2d8SCharles.Forsyth return real !int lv; 1666*0d13e2d8SCharles.Forsyth Ofact => 1667*0d13e2d8SCharles.Forsyth if(isinteger(lv) && lv >= 0.0){ 1668*0d13e2d8SCharles.Forsyth n := int lv; 1669*0d13e2d8SCharles.Forsyth lv = 1.0; 1670*0d13e2d8SCharles.Forsyth for(i := 2; i <= n; i++) 1671*0d13e2d8SCharles.Forsyth lv *= real i; 1672*0d13e2d8SCharles.Forsyth return lv; 1673*0d13e2d8SCharles.Forsyth } 1674*0d13e2d8SCharles.Forsyth return gamma(lv+1.0); 1675*0d13e2d8SCharles.Forsyth Ocom => 1676*0d13e2d8SCharles.Forsyth return real ~big lv; 1677*0d13e2d8SCharles.Forsyth Oas or 1678*0d13e2d8SCharles.Forsyth Odas => 1679*0d13e2d8SCharles.Forsyth l.dec.val = rv; 1680*0d13e2d8SCharles.Forsyth return rv; 1681*0d13e2d8SCharles.Forsyth Oplus => 1682*0d13e2d8SCharles.Forsyth return lv; 1683*0d13e2d8SCharles.Forsyth Ominus => 1684*0d13e2d8SCharles.Forsyth return -lv; 1685*0d13e2d8SCharles.Forsyth Oinv => 1686*0d13e2d8SCharles.Forsyth return 1.0/lv; 1687*0d13e2d8SCharles.Forsyth Ocomma => 1688*0d13e2d8SCharles.Forsyth return rv; 1689*0d13e2d8SCharles.Forsyth Oquest => 1690*0d13e2d8SCharles.Forsyth if(int lv) 1691*0d13e2d8SCharles.Forsyth return eval(r.left); 1692*0d13e2d8SCharles.Forsyth else 1693*0d13e2d8SCharles.Forsyth return eval(r.right); 1694*0d13e2d8SCharles.Forsyth Onand => 1695*0d13e2d8SCharles.Forsyth return real !(int lv&int rv); 1696*0d13e2d8SCharles.Forsyth Onor => 1697*0d13e2d8SCharles.Forsyth return real !(int lv|int rv); 1698*0d13e2d8SCharles.Forsyth Oimp => 1699*0d13e2d8SCharles.Forsyth return real (!int lv|int rv); 1700*0d13e2d8SCharles.Forsyth Oimpby => 1701*0d13e2d8SCharles.Forsyth return real (int lv|!int rv); 1702*0d13e2d8SCharles.Forsyth Oiff => 1703*0d13e2d8SCharles.Forsyth return real !(int lv^int rv); 1704*0d13e2d8SCharles.Forsyth * => 1705*0d13e2d8SCharles.Forsyth fatal(sys->sprint("case %s in eval", opstring(o))); 1706*0d13e2d8SCharles.Forsyth } 1707*0d13e2d8SCharles.Forsyth return 0.0; 1708*0d13e2d8SCharles.Forsyth} 1709*0d13e2d8SCharles.Forsyth 1710*0d13e2d8SCharles.Forsythvar(e: ref Node) 1711*0d13e2d8SCharles.Forsyth{ 1712*0d13e2d8SCharles.Forsyth if(e == nil || e.op != Ovar || e.dec.kind != Ovar) 1713*0d13e2d8SCharles.Forsyth error(e, "expected a variable"); 1714*0d13e2d8SCharles.Forsyth} 1715*0d13e2d8SCharles.Forsyth 1716*0d13e2d8SCharles.Forsythlibfun(o: int, a: ref Node): real 1717*0d13e2d8SCharles.Forsyth{ 1718*0d13e2d8SCharles.Forsyth a1, a2: real; 1719*0d13e2d8SCharles.Forsyth 1720*0d13e2d8SCharles.Forsyth case(o){ 1721*0d13e2d8SCharles.Forsyth Osolve => 1722*0d13e2d8SCharles.Forsyth return solve(a); 1723*0d13e2d8SCharles.Forsyth Osigma or 1724*0d13e2d8SCharles.Forsyth Opi or 1725*0d13e2d8SCharles.Forsyth Ocfrac => 1726*0d13e2d8SCharles.Forsyth return series(o, a); 1727*0d13e2d8SCharles.Forsyth Oderiv => 1728*0d13e2d8SCharles.Forsyth return differential(a); 1729*0d13e2d8SCharles.Forsyth Ointeg => 1730*0d13e2d8SCharles.Forsyth return integral(a); 1731*0d13e2d8SCharles.Forsyth } 1732*0d13e2d8SCharles.Forsyth v := 0.0; 1733*0d13e2d8SCharles.Forsyth if(a != nil && a.op == Ocomma){ 1734*0d13e2d8SCharles.Forsyth a1 = eval(a.left); 1735*0d13e2d8SCharles.Forsyth a2 = eval(a.right); 1736*0d13e2d8SCharles.Forsyth } 1737*0d13e2d8SCharles.Forsyth else 1738*0d13e2d8SCharles.Forsyth a1 = eval(a); 1739*0d13e2d8SCharles.Forsyth case(o){ 1740*0d13e2d8SCharles.Forsyth Olog => 1741*0d13e2d8SCharles.Forsyth v = maths->log(a1); 1742*0d13e2d8SCharles.Forsyth Olog10 => 1743*0d13e2d8SCharles.Forsyth v = maths->log10(a1); 1744*0d13e2d8SCharles.Forsyth Olog2 => 1745*0d13e2d8SCharles.Forsyth v = maths->log(a1)/maths->log(2.0); 1746*0d13e2d8SCharles.Forsyth Ologb => 1747*0d13e2d8SCharles.Forsyth v = maths->log(a1)/maths->log(a2); 1748*0d13e2d8SCharles.Forsyth Oexpf => 1749*0d13e2d8SCharles.Forsyth v = maths->exp(a1); 1750*0d13e2d8SCharles.Forsyth Opow => 1751*0d13e2d8SCharles.Forsyth v = maths->pow(a1, a2); 1752*0d13e2d8SCharles.Forsyth Osqrt => 1753*0d13e2d8SCharles.Forsyth v = maths->sqrt(a1); 1754*0d13e2d8SCharles.Forsyth Ocbrt => 1755*0d13e2d8SCharles.Forsyth v = maths->cbrt(a1); 1756*0d13e2d8SCharles.Forsyth Ofloor => 1757*0d13e2d8SCharles.Forsyth v = maths->floor(a1); 1758*0d13e2d8SCharles.Forsyth Oceil => 1759*0d13e2d8SCharles.Forsyth v = maths->ceil(a1); 1760*0d13e2d8SCharles.Forsyth Omin => 1761*0d13e2d8SCharles.Forsyth v = maths->fmin(a1, a2); 1762*0d13e2d8SCharles.Forsyth Omax => 1763*0d13e2d8SCharles.Forsyth v = maths->fmax(a1, a2); 1764*0d13e2d8SCharles.Forsyth Oabs => 1765*0d13e2d8SCharles.Forsyth v = maths->fabs(a1); 1766*0d13e2d8SCharles.Forsyth Ogamma => 1767*0d13e2d8SCharles.Forsyth v = gamma(a1); 1768*0d13e2d8SCharles.Forsyth Osign => 1769*0d13e2d8SCharles.Forsyth if(a1 > 0.0) 1770*0d13e2d8SCharles.Forsyth v = 1.0; 1771*0d13e2d8SCharles.Forsyth else if(a1 < 0.0) 1772*0d13e2d8SCharles.Forsyth v = -1.0; 1773*0d13e2d8SCharles.Forsyth else 1774*0d13e2d8SCharles.Forsyth v = 0.0; 1775*0d13e2d8SCharles.Forsyth Oint => 1776*0d13e2d8SCharles.Forsyth (vi, nil) := maths->modf(a1); 1777*0d13e2d8SCharles.Forsyth v = real vi; 1778*0d13e2d8SCharles.Forsyth Ofrac => 1779*0d13e2d8SCharles.Forsyth (nil, v) = maths->modf(a1); 1780*0d13e2d8SCharles.Forsyth Oround => 1781*0d13e2d8SCharles.Forsyth v = maths->rint(a1); 1782*0d13e2d8SCharles.Forsyth Oerf => 1783*0d13e2d8SCharles.Forsyth v = maths->erf(a1); 1784*0d13e2d8SCharles.Forsyth Osin => 1785*0d13e2d8SCharles.Forsyth v = maths->sin(D2R(a1)); 1786*0d13e2d8SCharles.Forsyth Ocos => 1787*0d13e2d8SCharles.Forsyth v = maths->cos(D2R(a1)); 1788*0d13e2d8SCharles.Forsyth Otan => 1789*0d13e2d8SCharles.Forsyth v = maths->tan(D2R(a1)); 1790*0d13e2d8SCharles.Forsyth Oasin => 1791*0d13e2d8SCharles.Forsyth v = R2D(maths->asin(a1)); 1792*0d13e2d8SCharles.Forsyth Oacos => 1793*0d13e2d8SCharles.Forsyth v = R2D(maths->acos(a1)); 1794*0d13e2d8SCharles.Forsyth Oatan => 1795*0d13e2d8SCharles.Forsyth v = R2D(maths->atan(a1)); 1796*0d13e2d8SCharles.Forsyth Oatan2 => 1797*0d13e2d8SCharles.Forsyth v = R2D(maths->atan2(a1, a2)); 1798*0d13e2d8SCharles.Forsyth Osinh => 1799*0d13e2d8SCharles.Forsyth v = maths->sinh(a1); 1800*0d13e2d8SCharles.Forsyth Ocosh => 1801*0d13e2d8SCharles.Forsyth v = maths->cosh(a1); 1802*0d13e2d8SCharles.Forsyth Otanh => 1803*0d13e2d8SCharles.Forsyth v = maths->tanh(a1); 1804*0d13e2d8SCharles.Forsyth Oasinh => 1805*0d13e2d8SCharles.Forsyth v = maths->asinh(a1); 1806*0d13e2d8SCharles.Forsyth Oacosh => 1807*0d13e2d8SCharles.Forsyth v = maths->acosh(a1); 1808*0d13e2d8SCharles.Forsyth Oatanh => 1809*0d13e2d8SCharles.Forsyth v = maths->atanh(a1); 1810*0d13e2d8SCharles.Forsyth Orand => 1811*0d13e2d8SCharles.Forsyth v = real rand->rand(Big)/real Big; 1812*0d13e2d8SCharles.Forsyth * => 1813*0d13e2d8SCharles.Forsyth fatal(sys->sprint("case %s in libfun", opstring(o))); 1814*0d13e2d8SCharles.Forsyth } 1815*0d13e2d8SCharles.Forsyth return v; 1816*0d13e2d8SCharles.Forsyth} 1817*0d13e2d8SCharles.Forsyth 1818*0d13e2d8SCharles.Forsythseries(o: int, a: ref Node): real 1819*0d13e2d8SCharles.Forsyth{ 1820*0d13e2d8SCharles.Forsyth p0, p1, q0, q1: real; 1821*0d13e2d8SCharles.Forsyth 1822*0d13e2d8SCharles.Forsyth l := a.left; 1823*0d13e2d8SCharles.Forsyth r := a.right; 1824*0d13e2d8SCharles.Forsyth if(o == Osigma) 1825*0d13e2d8SCharles.Forsyth v := 0.0; 1826*0d13e2d8SCharles.Forsyth else if(o == Opi) 1827*0d13e2d8SCharles.Forsyth v = 1.0; 1828*0d13e2d8SCharles.Forsyth else{ 1829*0d13e2d8SCharles.Forsyth p0 = q1 = 0.0; 1830*0d13e2d8SCharles.Forsyth p1 = q0 = 1.0; 1831*0d13e2d8SCharles.Forsyth v = Infinity; 1832*0d13e2d8SCharles.Forsyth } 1833*0d13e2d8SCharles.Forsyth i := l.left.left.dec; 1834*0d13e2d8SCharles.Forsyth ov := i.val; 1835*0d13e2d8SCharles.Forsyth i.val = eval(l.left.right); 1836*0d13e2d8SCharles.Forsyth eq := 0; 1837*0d13e2d8SCharles.Forsyth for(;;){ 1838*0d13e2d8SCharles.Forsyth rv := eval(l.right); 1839*0d13e2d8SCharles.Forsyth if(i.val > rv) 1840*0d13e2d8SCharles.Forsyth break; 1841*0d13e2d8SCharles.Forsyth lv := v; 1842*0d13e2d8SCharles.Forsyth ev := eval(r); 1843*0d13e2d8SCharles.Forsyth if(o == Osigma) 1844*0d13e2d8SCharles.Forsyth v += ev; 1845*0d13e2d8SCharles.Forsyth else if(o == Opi) 1846*0d13e2d8SCharles.Forsyth v *= ev; 1847*0d13e2d8SCharles.Forsyth else{ 1848*0d13e2d8SCharles.Forsyth t := ev*p1+p0; 1849*0d13e2d8SCharles.Forsyth p0 = p1; 1850*0d13e2d8SCharles.Forsyth p1 = t; 1851*0d13e2d8SCharles.Forsyth t = ev*q1+q0; 1852*0d13e2d8SCharles.Forsyth q0 = q1; 1853*0d13e2d8SCharles.Forsyth q1 = t; 1854*0d13e2d8SCharles.Forsyth v = p1/q1; 1855*0d13e2d8SCharles.Forsyth } 1856*0d13e2d8SCharles.Forsyth if(v == lv && rv == Infinity){ 1857*0d13e2d8SCharles.Forsyth eq++; 1858*0d13e2d8SCharles.Forsyth if(eq > 100) 1859*0d13e2d8SCharles.Forsyth break; 1860*0d13e2d8SCharles.Forsyth } 1861*0d13e2d8SCharles.Forsyth else 1862*0d13e2d8SCharles.Forsyth eq = 0; 1863*0d13e2d8SCharles.Forsyth i.val += 1.0; 1864*0d13e2d8SCharles.Forsyth } 1865*0d13e2d8SCharles.Forsyth i.val = ov; 1866*0d13e2d8SCharles.Forsyth return v; 1867*0d13e2d8SCharles.Forsyth} 1868*0d13e2d8SCharles.Forsyth 1869*0d13e2d8SCharles.Forsythpushe(a: ref Node, l: list of real): list of real 1870*0d13e2d8SCharles.Forsyth{ 1871*0d13e2d8SCharles.Forsyth if(a == nil) 1872*0d13e2d8SCharles.Forsyth return l; 1873*0d13e2d8SCharles.Forsyth if(a.op == Ocomma){ 1874*0d13e2d8SCharles.Forsyth l = pushe(a.left, l); 1875*0d13e2d8SCharles.Forsyth return pushe(a.right, l); 1876*0d13e2d8SCharles.Forsyth } 1877*0d13e2d8SCharles.Forsyth l = eval(a) :: l; 1878*0d13e2d8SCharles.Forsyth return l; 1879*0d13e2d8SCharles.Forsyth} 1880*0d13e2d8SCharles.Forsyth 1881*0d13e2d8SCharles.Forsythpusha(f: ref Node, l: list of real, nl: list of real): (list of real, list of real) 1882*0d13e2d8SCharles.Forsyth{ 1883*0d13e2d8SCharles.Forsyth if(f == nil) 1884*0d13e2d8SCharles.Forsyth return (l, nl); 1885*0d13e2d8SCharles.Forsyth if(f.op == Ocomma){ 1886*0d13e2d8SCharles.Forsyth (l, nl) = pusha(f.left, l, nl); 1887*0d13e2d8SCharles.Forsyth return pusha(f.right, l, nl); 1888*0d13e2d8SCharles.Forsyth } 1889*0d13e2d8SCharles.Forsyth l = f.dec.val :: l; 1890*0d13e2d8SCharles.Forsyth f.dec.val = hd nl; 1891*0d13e2d8SCharles.Forsyth return (l, tl nl); 1892*0d13e2d8SCharles.Forsyth} 1893*0d13e2d8SCharles.Forsyth 1894*0d13e2d8SCharles.Forsythpop(f: ref Node, l: list of real): list of real 1895*0d13e2d8SCharles.Forsyth{ 1896*0d13e2d8SCharles.Forsyth if(f == nil) 1897*0d13e2d8SCharles.Forsyth return l; 1898*0d13e2d8SCharles.Forsyth if(f.op == Ocomma){ 1899*0d13e2d8SCharles.Forsyth l = pop(f.left, l); 1900*0d13e2d8SCharles.Forsyth return pop(f.right, l); 1901*0d13e2d8SCharles.Forsyth } 1902*0d13e2d8SCharles.Forsyth f.dec.val = hd l; 1903*0d13e2d8SCharles.Forsyth return tl l; 1904*0d13e2d8SCharles.Forsyth} 1905*0d13e2d8SCharles.Forsyth 1906*0d13e2d8SCharles.Forsythrev(l: list of real): list of real 1907*0d13e2d8SCharles.Forsyth{ 1908*0d13e2d8SCharles.Forsyth nl: list of real; 1909*0d13e2d8SCharles.Forsyth 1910*0d13e2d8SCharles.Forsyth for( ; l != nil; l = tl l) 1911*0d13e2d8SCharles.Forsyth nl = hd l :: nl; 1912*0d13e2d8SCharles.Forsyth return nl; 1913*0d13e2d8SCharles.Forsyth} 1914*0d13e2d8SCharles.Forsyth 1915*0d13e2d8SCharles.Forsythcall(d: ref Dec, a: ref Node): real 1916*0d13e2d8SCharles.Forsyth{ 1917*0d13e2d8SCharles.Forsyth l: list of real; 1918*0d13e2d8SCharles.Forsyth 1919*0d13e2d8SCharles.Forsyth nl := rev(pushe(a, nil)); 1920*0d13e2d8SCharles.Forsyth (l, nil) = pusha(d.code.left, nil, nl); 1921*0d13e2d8SCharles.Forsyth l = rev(l); 1922*0d13e2d8SCharles.Forsyth (k, v) := estat(d.code.right); 1923*0d13e2d8SCharles.Forsyth l = pop(d.code.left, l); 1924*0d13e2d8SCharles.Forsyth if(k == Oexit) 1925*0d13e2d8SCharles.Forsyth exit; 1926*0d13e2d8SCharles.Forsyth return v; 1927*0d13e2d8SCharles.Forsyth} 1928*0d13e2d8SCharles.Forsyth 1929*0d13e2d8SCharles.Forsythprint(n: ref Node): real 1930*0d13e2d8SCharles.Forsyth{ 1931*0d13e2d8SCharles.Forsyth if(n == nil) 1932*0d13e2d8SCharles.Forsyth return 0.0; 1933*0d13e2d8SCharles.Forsyth if(n.op == Ocomma){ 1934*0d13e2d8SCharles.Forsyth print(n.left); 1935*0d13e2d8SCharles.Forsyth return print(n.right); 1936*0d13e2d8SCharles.Forsyth } 1937*0d13e2d8SCharles.Forsyth if(n.op == Ostring){ 1938*0d13e2d8SCharles.Forsyth sys->print("%s", n.str); 1939*0d13e2d8SCharles.Forsyth return 0.0; 1940*0d13e2d8SCharles.Forsyth } 1941*0d13e2d8SCharles.Forsyth v := eval(n); 1942*0d13e2d8SCharles.Forsyth printnum(v, ""); 1943*0d13e2d8SCharles.Forsyth return v; 1944*0d13e2d8SCharles.Forsyth} 1945*0d13e2d8SCharles.Forsyth 1946*0d13e2d8SCharles.Forsythread(n: ref Node): real 1947*0d13e2d8SCharles.Forsyth{ 1948*0d13e2d8SCharles.Forsyth bio: ref Iobuf; 1949*0d13e2d8SCharles.Forsyth 1950*0d13e2d8SCharles.Forsyth if(n == nil) 1951*0d13e2d8SCharles.Forsyth return 0.0; 1952*0d13e2d8SCharles.Forsyth if(n.op == Ocomma){ 1953*0d13e2d8SCharles.Forsyth read(n.left); 1954*0d13e2d8SCharles.Forsyth return read(n.right); 1955*0d13e2d8SCharles.Forsyth } 1956*0d13e2d8SCharles.Forsyth sys->print("%s ? ", n.dec.sym.name); 1957*0d13e2d8SCharles.Forsyth if(!stdin){ 1958*0d13e2d8SCharles.Forsyth bio = bufio->fopen(sys->fildes(0), Sys->OREAD); 1959*0d13e2d8SCharles.Forsyth stack(nil, bio); 1960*0d13e2d8SCharles.Forsyth } 1961*0d13e2d8SCharles.Forsyth lexnum(); 1962*0d13e2d8SCharles.Forsyth consume(Onl); 1963*0d13e2d8SCharles.Forsyth n.dec.val = lexval; 1964*0d13e2d8SCharles.Forsyth if(!stdin && bin == bio) 1965*0d13e2d8SCharles.Forsyth unstack(); 1966*0d13e2d8SCharles.Forsyth return n.dec.val; 1967*0d13e2d8SCharles.Forsyth} 1968*0d13e2d8SCharles.Forsyth 1969*0d13e2d8SCharles.Forsythisint(v: real): int 1970*0d13e2d8SCharles.Forsyth{ 1971*0d13e2d8SCharles.Forsyth return v >= -real Maxint && v <= real Maxint; 1972*0d13e2d8SCharles.Forsyth} 1973*0d13e2d8SCharles.Forsyth 1974*0d13e2d8SCharles.Forsythisinteger(v: real): int 1975*0d13e2d8SCharles.Forsyth{ 1976*0d13e2d8SCharles.Forsyth return v == real int v && isint(v); 1977*0d13e2d8SCharles.Forsyth} 1978*0d13e2d8SCharles.Forsyth 1979*0d13e2d8SCharles.Forsythsplit(v: real): (int, real) 1980*0d13e2d8SCharles.Forsyth{ 1981*0d13e2d8SCharles.Forsyth # v >= 0.0 1982*0d13e2d8SCharles.Forsyth n := int v; 1983*0d13e2d8SCharles.Forsyth if(real n > v) 1984*0d13e2d8SCharles.Forsyth n--; 1985*0d13e2d8SCharles.Forsyth return (n, v-real n); 1986*0d13e2d8SCharles.Forsyth} 1987*0d13e2d8SCharles.Forsyth 1988*0d13e2d8SCharles.Forsythn2c(n: int): int 1989*0d13e2d8SCharles.Forsyth{ 1990*0d13e2d8SCharles.Forsyth if(n < 10) 1991*0d13e2d8SCharles.Forsyth return n+'0'; 1992*0d13e2d8SCharles.Forsyth return n-10+'a'; 1993*0d13e2d8SCharles.Forsyth} 1994*0d13e2d8SCharles.Forsyth 1995*0d13e2d8SCharles.Forsythgamma(v: real): real 1996*0d13e2d8SCharles.Forsyth{ 1997*0d13e2d8SCharles.Forsyth (s, lg) := maths->lgamma(v); 1998*0d13e2d8SCharles.Forsyth return real s*maths->exp(lg); 1999*0d13e2d8SCharles.Forsyth} 2000*0d13e2d8SCharles.Forsyth 2001*0d13e2d8SCharles.ForsythD2R(a: real): real 2002*0d13e2d8SCharles.Forsyth{ 2003*0d13e2d8SCharles.Forsyth if(deg.val != 0.0) 2004*0d13e2d8SCharles.Forsyth a *= Pi/180.0; 2005*0d13e2d8SCharles.Forsyth return a; 2006*0d13e2d8SCharles.Forsyth} 2007*0d13e2d8SCharles.Forsyth 2008*0d13e2d8SCharles.ForsythR2D(a: real): real 2009*0d13e2d8SCharles.Forsyth{ 2010*0d13e2d8SCharles.Forsyth if(deg.val != 0.0) 2011*0d13e2d8SCharles.Forsyth a /= Pi/180.0; 2012*0d13e2d8SCharles.Forsyth return a; 2013*0d13e2d8SCharles.Forsyth} 2014*0d13e2d8SCharles.Forsyth 2015*0d13e2d8SCharles.Forsythside(n: ref Node): int 2016*0d13e2d8SCharles.Forsyth{ 2017*0d13e2d8SCharles.Forsyth if(n == nil) 2018*0d13e2d8SCharles.Forsyth return 0; 2019*0d13e2d8SCharles.Forsyth if(asop(n.op) || n.op == Ofun) 2020*0d13e2d8SCharles.Forsyth return 1; 2021*0d13e2d8SCharles.Forsyth return side(n.left) || side(n.right); 2022*0d13e2d8SCharles.Forsyth} 2023*0d13e2d8SCharles.Forsyth 2024*0d13e2d8SCharles.Forsythsametree(n1: ref Node, n2: ref Node): int 2025*0d13e2d8SCharles.Forsyth{ 2026*0d13e2d8SCharles.Forsyth if(n1 == n2) 2027*0d13e2d8SCharles.Forsyth return 1; 2028*0d13e2d8SCharles.Forsyth if(n1 == nil || n2 == nil) 2029*0d13e2d8SCharles.Forsyth return 0; 2030*0d13e2d8SCharles.Forsyth if(n1.op != n2.op) 2031*0d13e2d8SCharles.Forsyth return 0; 2032*0d13e2d8SCharles.Forsyth case(n1.op){ 2033*0d13e2d8SCharles.Forsyth Ostring => 2034*0d13e2d8SCharles.Forsyth return n1.str == n2.str; 2035*0d13e2d8SCharles.Forsyth Onum => 2036*0d13e2d8SCharles.Forsyth return n1.val == n2.val; 2037*0d13e2d8SCharles.Forsyth Ocon or 2038*0d13e2d8SCharles.Forsyth Ovar => 2039*0d13e2d8SCharles.Forsyth return n1.dec == n2.dec; 2040*0d13e2d8SCharles.Forsyth Ofun or 2041*0d13e2d8SCharles.Forsyth Olfun => 2042*0d13e2d8SCharles.Forsyth return n1.dec == n2.dec && sametree(n1.left, n2.left); 2043*0d13e2d8SCharles.Forsyth * => 2044*0d13e2d8SCharles.Forsyth return sametree(n1.left, n2.left) && sametree(n1.right, n2.right); 2045*0d13e2d8SCharles.Forsyth } 2046*0d13e2d8SCharles.Forsyth return 0; 2047*0d13e2d8SCharles.Forsyth} 2048*0d13e2d8SCharles.Forsyth 2049*0d13e2d8SCharles.Forsythsimplify(n: ref Node): ref Node 2050*0d13e2d8SCharles.Forsyth{ 2051*0d13e2d8SCharles.Forsyth if(n == nil) 2052*0d13e2d8SCharles.Forsyth return nil; 2053*0d13e2d8SCharles.Forsyth op := n.op; 2054*0d13e2d8SCharles.Forsyth l := n.left = simplify(n.left); 2055*0d13e2d8SCharles.Forsyth r := n.right = simplify(n.right); 2056*0d13e2d8SCharles.Forsyth if(l != nil && iscon(l) && (r == nil || iscon(r))){ 2057*0d13e2d8SCharles.Forsyth if(isnan(l)) 2058*0d13e2d8SCharles.Forsyth return l; 2059*0d13e2d8SCharles.Forsyth if(r != nil && isnan(r)) 2060*0d13e2d8SCharles.Forsyth return r; 2061*0d13e2d8SCharles.Forsyth return vtree(eval(n)); 2062*0d13e2d8SCharles.Forsyth } 2063*0d13e2d8SCharles.Forsyth case(op){ 2064*0d13e2d8SCharles.Forsyth Onum or 2065*0d13e2d8SCharles.Forsyth Ocon or 2066*0d13e2d8SCharles.Forsyth Ovar or 2067*0d13e2d8SCharles.Forsyth Olfun or 2068*0d13e2d8SCharles.Forsyth Ocomma => 2069*0d13e2d8SCharles.Forsyth return n; 2070*0d13e2d8SCharles.Forsyth Oplus => 2071*0d13e2d8SCharles.Forsyth return l; 2072*0d13e2d8SCharles.Forsyth Ominus => 2073*0d13e2d8SCharles.Forsyth if(l.op == Ominus) 2074*0d13e2d8SCharles.Forsyth return l.left; 2075*0d13e2d8SCharles.Forsyth Oinv => 2076*0d13e2d8SCharles.Forsyth if(l.op == Oinv) 2077*0d13e2d8SCharles.Forsyth return l.left; 2078*0d13e2d8SCharles.Forsyth Oadd => 2079*0d13e2d8SCharles.Forsyth if(iszero(l)) 2080*0d13e2d8SCharles.Forsyth return r; 2081*0d13e2d8SCharles.Forsyth if(iszero(r)) 2082*0d13e2d8SCharles.Forsyth return l; 2083*0d13e2d8SCharles.Forsyth if(sametree(l, r)) 2084*0d13e2d8SCharles.Forsyth return tree(Omul, itree(2), l); 2085*0d13e2d8SCharles.Forsyth Osub => 2086*0d13e2d8SCharles.Forsyth if(iszero(l)) 2087*0d13e2d8SCharles.Forsyth return simplify(tree(Ominus, r, nil)); 2088*0d13e2d8SCharles.Forsyth if(iszero(r)) 2089*0d13e2d8SCharles.Forsyth return l; 2090*0d13e2d8SCharles.Forsyth if(sametree(l, r)) 2091*0d13e2d8SCharles.Forsyth return itree(0); 2092*0d13e2d8SCharles.Forsyth Omul => 2093*0d13e2d8SCharles.Forsyth if(iszero(l)) 2094*0d13e2d8SCharles.Forsyth return l; 2095*0d13e2d8SCharles.Forsyth if(iszero(r)) 2096*0d13e2d8SCharles.Forsyth return r; 2097*0d13e2d8SCharles.Forsyth if(isone(l)) 2098*0d13e2d8SCharles.Forsyth return r; 2099*0d13e2d8SCharles.Forsyth if(isone(r)) 2100*0d13e2d8SCharles.Forsyth return l; 2101*0d13e2d8SCharles.Forsyth if(sametree(l, r)) 2102*0d13e2d8SCharles.Forsyth return tree(Oexp, l, itree(2)); 2103*0d13e2d8SCharles.Forsyth Odiv => 2104*0d13e2d8SCharles.Forsyth if(iszero(l)) 2105*0d13e2d8SCharles.Forsyth return l; 2106*0d13e2d8SCharles.Forsyth if(iszero(r)) 2107*0d13e2d8SCharles.Forsyth return vtree(Infinity); 2108*0d13e2d8SCharles.Forsyth if(isone(l)) 2109*0d13e2d8SCharles.Forsyth return ptree(r, -1.0); 2110*0d13e2d8SCharles.Forsyth if(isone(r)) 2111*0d13e2d8SCharles.Forsyth return l; 2112*0d13e2d8SCharles.Forsyth if(sametree(l, r)) 2113*0d13e2d8SCharles.Forsyth return itree(1); 2114*0d13e2d8SCharles.Forsyth Oexp => 2115*0d13e2d8SCharles.Forsyth if(iszero(l)) 2116*0d13e2d8SCharles.Forsyth return l; 2117*0d13e2d8SCharles.Forsyth if(iszero(r)) 2118*0d13e2d8SCharles.Forsyth return itree(1); 2119*0d13e2d8SCharles.Forsyth if(isone(l)) 2120*0d13e2d8SCharles.Forsyth return l; 2121*0d13e2d8SCharles.Forsyth if(isone(r)) 2122*0d13e2d8SCharles.Forsyth return l; 2123*0d13e2d8SCharles.Forsyth * => 2124*0d13e2d8SCharles.Forsyth fatal(sys->sprint("case %s in simplify", opstring(op))); 2125*0d13e2d8SCharles.Forsyth } 2126*0d13e2d8SCharles.Forsyth return n; 2127*0d13e2d8SCharles.Forsyth} 2128*0d13e2d8SCharles.Forsyth 2129*0d13e2d8SCharles.Forsythderiv(n: ref Node, d: ref Dec): ref Node 2130*0d13e2d8SCharles.Forsyth{ 2131*0d13e2d8SCharles.Forsyth if(n == nil) 2132*0d13e2d8SCharles.Forsyth return nil; 2133*0d13e2d8SCharles.Forsyth op := n.op; 2134*0d13e2d8SCharles.Forsyth l := n.left; 2135*0d13e2d8SCharles.Forsyth r := n.right; 2136*0d13e2d8SCharles.Forsyth case(op){ 2137*0d13e2d8SCharles.Forsyth Onum or 2138*0d13e2d8SCharles.Forsyth Ocon => 2139*0d13e2d8SCharles.Forsyth n = itree(0); 2140*0d13e2d8SCharles.Forsyth Ovar => 2141*0d13e2d8SCharles.Forsyth if(d == n.dec) 2142*0d13e2d8SCharles.Forsyth n = itree(1); 2143*0d13e2d8SCharles.Forsyth else 2144*0d13e2d8SCharles.Forsyth n = itree(0); 2145*0d13e2d8SCharles.Forsyth Olfun => 2146*0d13e2d8SCharles.Forsyth case(int n.dec.val){ 2147*0d13e2d8SCharles.Forsyth Olog => 2148*0d13e2d8SCharles.Forsyth n = ptree(l, -1.0); 2149*0d13e2d8SCharles.Forsyth Olog10 => 2150*0d13e2d8SCharles.Forsyth n = ptree(tree(Omul, l, vtree(Ln10)), -1.0); 2151*0d13e2d8SCharles.Forsyth Olog2 => 2152*0d13e2d8SCharles.Forsyth n = ptree(tree(Omul, l, vtree(Ln2)), -1.0); 2153*0d13e2d8SCharles.Forsyth Oexpf => 2154*0d13e2d8SCharles.Forsyth n = n; 2155*0d13e2d8SCharles.Forsyth Opow => 2156*0d13e2d8SCharles.Forsyth return deriv(tree(Oexp, l.left, l.right), d); 2157*0d13e2d8SCharles.Forsyth Osqrt => 2158*0d13e2d8SCharles.Forsyth return deriv(tree(Oexp, l, vtree(0.5)), d); 2159*0d13e2d8SCharles.Forsyth Ocbrt => 2160*0d13e2d8SCharles.Forsyth return deriv(tree(Oexp, l, vtree(1.0/3.0)), d); 2161*0d13e2d8SCharles.Forsyth Osin => 2162*0d13e2d8SCharles.Forsyth n = ltree("cos", l); 2163*0d13e2d8SCharles.Forsyth Ocos => 2164*0d13e2d8SCharles.Forsyth n = tree(Ominus, ltree("sin", l), nil); 2165*0d13e2d8SCharles.Forsyth Otan => 2166*0d13e2d8SCharles.Forsyth n = ptree(ltree("cos", l), -2.0); 2167*0d13e2d8SCharles.Forsyth Oasin => 2168*0d13e2d8SCharles.Forsyth n = ptree(tree(Osub, itree(1), ptree(l, 2.0)), -0.5); 2169*0d13e2d8SCharles.Forsyth Oacos => 2170*0d13e2d8SCharles.Forsyth n = tree(Ominus, ptree(tree(Osub, itree(1), ptree(l, 2.0)), -0.5), nil); 2171*0d13e2d8SCharles.Forsyth Oatan => 2172*0d13e2d8SCharles.Forsyth n = ptree(tree(Oadd, itree(1), ptree(l, 2.0)), -1.0); 2173*0d13e2d8SCharles.Forsyth Osinh => 2174*0d13e2d8SCharles.Forsyth n = ltree("cosh", l); 2175*0d13e2d8SCharles.Forsyth Ocosh => 2176*0d13e2d8SCharles.Forsyth n = ltree("sinh", l); 2177*0d13e2d8SCharles.Forsyth Otanh => 2178*0d13e2d8SCharles.Forsyth n = ptree(ltree("cosh", l), -2.0); 2179*0d13e2d8SCharles.Forsyth Oasinh => 2180*0d13e2d8SCharles.Forsyth n = ptree(tree(Oadd, itree(1), ptree(l, 2.0)), -0.5); 2181*0d13e2d8SCharles.Forsyth Oacosh => 2182*0d13e2d8SCharles.Forsyth n = ptree(tree(Osub, ptree(l, 2.0), itree(1)), -0.5); 2183*0d13e2d8SCharles.Forsyth Oatanh => 2184*0d13e2d8SCharles.Forsyth n = ptree(tree(Osub, itree(1), ptree(l, 2.0)), -1.0); 2185*0d13e2d8SCharles.Forsyth * => 2186*0d13e2d8SCharles.Forsyth return vtree(Nan); 2187*0d13e2d8SCharles.Forsyth } 2188*0d13e2d8SCharles.Forsyth return tree(Omul, n, deriv(l, d)); 2189*0d13e2d8SCharles.Forsyth Oplus or 2190*0d13e2d8SCharles.Forsyth Ominus => 2191*0d13e2d8SCharles.Forsyth n = tree(op, deriv(l, d), nil); 2192*0d13e2d8SCharles.Forsyth Oinv => 2193*0d13e2d8SCharles.Forsyth n = tree(Omul, tree(Ominus, ptree(l, -2.0), nil), deriv(l, d)); 2194*0d13e2d8SCharles.Forsyth Oadd or 2195*0d13e2d8SCharles.Forsyth Osub or 2196*0d13e2d8SCharles.Forsyth Ocomma => 2197*0d13e2d8SCharles.Forsyth n = tree(op, deriv(l, d), deriv(r, d)); 2198*0d13e2d8SCharles.Forsyth Omul => 2199*0d13e2d8SCharles.Forsyth n = tree(Oadd, tree(Omul, deriv(l, d), r), tree(Omul, l, deriv(r, d))); 2200*0d13e2d8SCharles.Forsyth Odiv => 2201*0d13e2d8SCharles.Forsyth n = tree(Osub, tree(Omul, deriv(l, d), r), tree(Omul, l, deriv(r, d))); 2202*0d13e2d8SCharles.Forsyth n = tree(Odiv, n, ptree(r, 2.0)); 2203*0d13e2d8SCharles.Forsyth Oexp => 2204*0d13e2d8SCharles.Forsyth nn := tree(Oadd, tree(Omul, deriv(l, d), tree(Odiv, r, l)), tree(Omul, ltree("log", l), deriv(r, d))); 2205*0d13e2d8SCharles.Forsyth n = tree(Omul, n, nn); 2206*0d13e2d8SCharles.Forsyth * => 2207*0d13e2d8SCharles.Forsyth n = vtree(Nan); 2208*0d13e2d8SCharles.Forsyth } 2209*0d13e2d8SCharles.Forsyth return n; 2210*0d13e2d8SCharles.Forsyth} 2211*0d13e2d8SCharles.Forsyth 2212*0d13e2d8SCharles.Forsythderivative(n: ref Node, d: ref Dec): ref Node 2213*0d13e2d8SCharles.Forsyth{ 2214*0d13e2d8SCharles.Forsyth n = simplify(deriv(n, d)); 2215*0d13e2d8SCharles.Forsyth if(isnan(n)) 2216*0d13e2d8SCharles.Forsyth error(n, "no derivative"); 2217*0d13e2d8SCharles.Forsyth if(debug) 2218*0d13e2d8SCharles.Forsyth prnode(n); 2219*0d13e2d8SCharles.Forsyth return n; 2220*0d13e2d8SCharles.Forsyth} 2221*0d13e2d8SCharles.Forsyth 2222*0d13e2d8SCharles.Forsythnewton(f: ref Node, e: ref Node, d: ref Dec, v1: real, v2: real): (int, real) 2223*0d13e2d8SCharles.Forsyth{ 2224*0d13e2d8SCharles.Forsyth v := (v1+v2)/2.0; 2225*0d13e2d8SCharles.Forsyth lv := 0.0; 2226*0d13e2d8SCharles.Forsyth its := 0; 2227*0d13e2d8SCharles.Forsyth for(;;){ 2228*0d13e2d8SCharles.Forsyth lv = v; 2229*0d13e2d8SCharles.Forsyth d.val = v; 2230*0d13e2d8SCharles.Forsyth v = eval(e); 2231*0d13e2d8SCharles.Forsyth # if(v < v1 || v > v2) 2232*0d13e2d8SCharles.Forsyth # return (0, 0.0); 2233*0d13e2d8SCharles.Forsyth if(maths->isnan(v)) 2234*0d13e2d8SCharles.Forsyth return (0, 0.0); 2235*0d13e2d8SCharles.Forsyth if(its > 100 || fabs(v-lv) < Eps) 2236*0d13e2d8SCharles.Forsyth break; 2237*0d13e2d8SCharles.Forsyth its++; 2238*0d13e2d8SCharles.Forsyth } 2239*0d13e2d8SCharles.Forsyth if(fabs(v-lv) > Bigeps || fabs(eval(f)) > Bigeps) 2240*0d13e2d8SCharles.Forsyth return (0, 0.0); 2241*0d13e2d8SCharles.Forsyth return (1, v); 2242*0d13e2d8SCharles.Forsyth} 2243*0d13e2d8SCharles.Forsyth 2244*0d13e2d8SCharles.Forsythsolve(n: ref Node): real 2245*0d13e2d8SCharles.Forsyth{ 2246*0d13e2d8SCharles.Forsyth d: ref Dec; 2247*0d13e2d8SCharles.Forsyth 2248*0d13e2d8SCharles.Forsyth if(n == nil) 2249*0d13e2d8SCharles.Forsyth return Nan; 2250*0d13e2d8SCharles.Forsyth if(n.op == Ocomma){ # solve(..., var) 2251*0d13e2d8SCharles.Forsyth var(n.right); 2252*0d13e2d8SCharles.Forsyth d = n.right.dec; 2253*0d13e2d8SCharles.Forsyth n = n.left; 2254*0d13e2d8SCharles.Forsyth if(!varmem(n, d)) 2255*0d13e2d8SCharles.Forsyth error(n, "variable not in equation"); 2256*0d13e2d8SCharles.Forsyth } 2257*0d13e2d8SCharles.Forsyth else{ 2258*0d13e2d8SCharles.Forsyth d = findvar(n, nil); 2259*0d13e2d8SCharles.Forsyth if(d == nil) 2260*0d13e2d8SCharles.Forsyth error(n, "variable missing"); 2261*0d13e2d8SCharles.Forsyth if(d == errdec) 2262*0d13e2d8SCharles.Forsyth error(n, "one variable only required"); 2263*0d13e2d8SCharles.Forsyth } 2264*0d13e2d8SCharles.Forsyth if(n.op == Oeq) 2265*0d13e2d8SCharles.Forsyth n.op = Osub; 2266*0d13e2d8SCharles.Forsyth dn := derivative(n, d); 2267*0d13e2d8SCharles.Forsyth var := tree(Ovar, nil, nil); 2268*0d13e2d8SCharles.Forsyth var.dec = d; 2269*0d13e2d8SCharles.Forsyth nr := tree(Osub, var, tree(Odiv, n, dn)); 2270*0d13e2d8SCharles.Forsyth ov := d.val; 2271*0d13e2d8SCharles.Forsyth lim := lookup(Limit).dec.val; 2272*0d13e2d8SCharles.Forsyth step := lookup(Step).dec.val; 2273*0d13e2d8SCharles.Forsyth rval := Infinity; 2274*0d13e2d8SCharles.Forsyth d.val = -lim-step; 2275*0d13e2d8SCharles.Forsyth v1 := 0.0; 2276*0d13e2d8SCharles.Forsyth v2 := eval(n); 2277*0d13e2d8SCharles.Forsyth for(v := -lim; v <= lim; v += step){ 2278*0d13e2d8SCharles.Forsyth d.val = v; 2279*0d13e2d8SCharles.Forsyth v1 = v2; 2280*0d13e2d8SCharles.Forsyth v2 = eval(n); 2281*0d13e2d8SCharles.Forsyth if(maths->isnan(v2)) # v == nan, v <= nan, v >= nan all give 1 2282*0d13e2d8SCharles.Forsyth continue; 2283*0d13e2d8SCharles.Forsyth if(fabs(v2) < Eps){ 2284*0d13e2d8SCharles.Forsyth if(v >= -lim && v <= lim && v != rval){ 2285*0d13e2d8SCharles.Forsyth printnum(v, " "); 2286*0d13e2d8SCharles.Forsyth rval = v; 2287*0d13e2d8SCharles.Forsyth } 2288*0d13e2d8SCharles.Forsyth } 2289*0d13e2d8SCharles.Forsyth else if(v1*v2 <= 0.0){ 2290*0d13e2d8SCharles.Forsyth (f, rv) := newton(n, nr, var.dec, v-step, v); 2291*0d13e2d8SCharles.Forsyth if(f && rv >= -lim && rv <= lim && rv != rval){ 2292*0d13e2d8SCharles.Forsyth printnum(rv, " "); 2293*0d13e2d8SCharles.Forsyth rval = rv; 2294*0d13e2d8SCharles.Forsyth } 2295*0d13e2d8SCharles.Forsyth } 2296*0d13e2d8SCharles.Forsyth } 2297*0d13e2d8SCharles.Forsyth d.val = ov; 2298*0d13e2d8SCharles.Forsyth if(rval == Infinity) 2299*0d13e2d8SCharles.Forsyth error(n, "no roots found"); 2300*0d13e2d8SCharles.Forsyth else 2301*0d13e2d8SCharles.Forsyth sys->print("\n"); 2302*0d13e2d8SCharles.Forsyth return rval; 2303*0d13e2d8SCharles.Forsyth} 2304*0d13e2d8SCharles.Forsyth 2305*0d13e2d8SCharles.Forsythdifferential(n: ref Node): real 2306*0d13e2d8SCharles.Forsyth{ 2307*0d13e2d8SCharles.Forsyth x := n.left.left.dec; 2308*0d13e2d8SCharles.Forsyth ov := x.val; 2309*0d13e2d8SCharles.Forsyth v := evalx(derivative(n.right, x), x, eval(n.left.right)); 2310*0d13e2d8SCharles.Forsyth x.val = ov; 2311*0d13e2d8SCharles.Forsyth return v; 2312*0d13e2d8SCharles.Forsyth} 2313*0d13e2d8SCharles.Forsyth 2314*0d13e2d8SCharles.Forsythintegral(n: ref Node): real 2315*0d13e2d8SCharles.Forsyth{ 2316*0d13e2d8SCharles.Forsyth l := n.left; 2317*0d13e2d8SCharles.Forsyth r := n.right; 2318*0d13e2d8SCharles.Forsyth x := l.left.left.dec; 2319*0d13e2d8SCharles.Forsyth ov := x.val; 2320*0d13e2d8SCharles.Forsyth a := eval(l.left.right); 2321*0d13e2d8SCharles.Forsyth b := eval(l.right); 2322*0d13e2d8SCharles.Forsyth h := b-a; 2323*0d13e2d8SCharles.Forsyth end := evalx(r, x, a) + evalx(r, x, b); 2324*0d13e2d8SCharles.Forsyth odd := even := 0.0; 2325*0d13e2d8SCharles.Forsyth oldarea := 0.0; 2326*0d13e2d8SCharles.Forsyth area := h*end/2.0; 2327*0d13e2d8SCharles.Forsyth for(i := 1; i < 1<<16; i <<= 1){ 2328*0d13e2d8SCharles.Forsyth even += odd; 2329*0d13e2d8SCharles.Forsyth odd = 0.0; 2330*0d13e2d8SCharles.Forsyth xv := a+h/2.0; 2331*0d13e2d8SCharles.Forsyth for(j := 0; j < i; j++){ 2332*0d13e2d8SCharles.Forsyth odd += evalx(r, x, xv); 2333*0d13e2d8SCharles.Forsyth xv += h; 2334*0d13e2d8SCharles.Forsyth } 2335*0d13e2d8SCharles.Forsyth h /= 2.0; 2336*0d13e2d8SCharles.Forsyth oldarea = area; 2337*0d13e2d8SCharles.Forsyth area = h*(end+4.0*odd+2.0*even)/3.0; 2338*0d13e2d8SCharles.Forsyth if(maths->isnan(area)) 2339*0d13e2d8SCharles.Forsyth error(n, "integral not found"); 2340*0d13e2d8SCharles.Forsyth if(fabs(area-oldarea) < Eps) 2341*0d13e2d8SCharles.Forsyth break; 2342*0d13e2d8SCharles.Forsyth } 2343*0d13e2d8SCharles.Forsyth if(fabs(area-oldarea) > Bigeps) 2344*0d13e2d8SCharles.Forsyth error(n, "integral not found"); 2345*0d13e2d8SCharles.Forsyth x.val = ov; 2346*0d13e2d8SCharles.Forsyth return area; 2347*0d13e2d8SCharles.Forsyth} 2348*0d13e2d8SCharles.Forsyth 2349*0d13e2d8SCharles.Forsythevalx(n: ref Node, d: ref Dec, v: real): real 2350*0d13e2d8SCharles.Forsyth{ 2351*0d13e2d8SCharles.Forsyth d.val = v; 2352*0d13e2d8SCharles.Forsyth return eval(n); 2353*0d13e2d8SCharles.Forsyth} 2354*0d13e2d8SCharles.Forsyth 2355*0d13e2d8SCharles.Forsythfindvar(n: ref Node, d: ref Dec): ref Dec 2356*0d13e2d8SCharles.Forsyth{ 2357*0d13e2d8SCharles.Forsyth if(n == nil) 2358*0d13e2d8SCharles.Forsyth return d; 2359*0d13e2d8SCharles.Forsyth d = findvar(n.left, d); 2360*0d13e2d8SCharles.Forsyth d = findvar(n.right, d); 2361*0d13e2d8SCharles.Forsyth if(n.op == Ovar){ 2362*0d13e2d8SCharles.Forsyth if(d == nil) 2363*0d13e2d8SCharles.Forsyth d = n.dec; 2364*0d13e2d8SCharles.Forsyth if(n.dec != d) 2365*0d13e2d8SCharles.Forsyth d = errdec; 2366*0d13e2d8SCharles.Forsyth } 2367*0d13e2d8SCharles.Forsyth return d; 2368*0d13e2d8SCharles.Forsyth} 2369*0d13e2d8SCharles.Forsyth 2370*0d13e2d8SCharles.Forsythvarmem(n: ref Node, d: ref Dec): int 2371*0d13e2d8SCharles.Forsyth{ 2372*0d13e2d8SCharles.Forsyth if(n == nil) 2373*0d13e2d8SCharles.Forsyth return 0; 2374*0d13e2d8SCharles.Forsyth if(n.op == Ovar) 2375*0d13e2d8SCharles.Forsyth return d == n.dec; 2376*0d13e2d8SCharles.Forsyth return varmem(n.left, d) || varmem(n.right, d); 2377*0d13e2d8SCharles.Forsyth} 2378*0d13e2d8SCharles.Forsyth 2379*0d13e2d8SCharles.Forsythfabs(r: real): real 2380*0d13e2d8SCharles.Forsyth{ 2381*0d13e2d8SCharles.Forsyth if(r < 0.0) 2382*0d13e2d8SCharles.Forsyth return -r; 2383*0d13e2d8SCharles.Forsyth return r; 2384*0d13e2d8SCharles.Forsyth} 2385*0d13e2d8SCharles.Forsyth 2386*0d13e2d8SCharles.Forsythcvt(v: real, base: int): string 2387*0d13e2d8SCharles.Forsyth{ 2388*0d13e2d8SCharles.Forsyth if(base == 10) 2389*0d13e2d8SCharles.Forsyth return sys->sprint("%g", v); 2390*0d13e2d8SCharles.Forsyth neg := 0; 2391*0d13e2d8SCharles.Forsyth if(v < 0.0){ 2392*0d13e2d8SCharles.Forsyth neg = 1; 2393*0d13e2d8SCharles.Forsyth v = -v; 2394*0d13e2d8SCharles.Forsyth } 2395*0d13e2d8SCharles.Forsyth if(!isint(v)){ 2396*0d13e2d8SCharles.Forsyth n := 0; 2397*0d13e2d8SCharles.Forsyth lg := maths->log(v)/maths->log(real base); 2398*0d13e2d8SCharles.Forsyth if(lg < 0.0){ 2399*0d13e2d8SCharles.Forsyth (n, nil) = split(-lg); 2400*0d13e2d8SCharles.Forsyth v *= real base**n; 2401*0d13e2d8SCharles.Forsyth n = -n; 2402*0d13e2d8SCharles.Forsyth } 2403*0d13e2d8SCharles.Forsyth else{ 2404*0d13e2d8SCharles.Forsyth (n, nil) = split(lg); 2405*0d13e2d8SCharles.Forsyth v /= real base**n; 2406*0d13e2d8SCharles.Forsyth } 2407*0d13e2d8SCharles.Forsyth s := cvt(v, base) + "E" + string n; 2408*0d13e2d8SCharles.Forsyth if(neg) 2409*0d13e2d8SCharles.Forsyth s = "-" + s; 2410*0d13e2d8SCharles.Forsyth return s; 2411*0d13e2d8SCharles.Forsyth } 2412*0d13e2d8SCharles.Forsyth (n, f) := split(v); 2413*0d13e2d8SCharles.Forsyth s := ""; 2414*0d13e2d8SCharles.Forsyth do{ 2415*0d13e2d8SCharles.Forsyth r := n%base; 2416*0d13e2d8SCharles.Forsyth n /= base; 2417*0d13e2d8SCharles.Forsyth s[len s] = n2c(r); 2418*0d13e2d8SCharles.Forsyth }while(n != 0); 2419*0d13e2d8SCharles.Forsyth ls := len s; 2420*0d13e2d8SCharles.Forsyth for(i := 0; i < ls/2; i++){ 2421*0d13e2d8SCharles.Forsyth t := s[i]; 2422*0d13e2d8SCharles.Forsyth s[i] = s[ls-1-i]; 2423*0d13e2d8SCharles.Forsyth s[ls-1-i] = t; 2424*0d13e2d8SCharles.Forsyth } 2425*0d13e2d8SCharles.Forsyth if(f != 0.0){ 2426*0d13e2d8SCharles.Forsyth s[len s] = '.'; 2427*0d13e2d8SCharles.Forsyth for(i = 0; i < 16 && f != 0.0; i++){ 2428*0d13e2d8SCharles.Forsyth f *= real base; 2429*0d13e2d8SCharles.Forsyth (n, f) = split(f); 2430*0d13e2d8SCharles.Forsyth s[len s] = n2c(n); 2431*0d13e2d8SCharles.Forsyth } 2432*0d13e2d8SCharles.Forsyth } 2433*0d13e2d8SCharles.Forsyth s = string base + "r" + s; 2434*0d13e2d8SCharles.Forsyth if(neg) 2435*0d13e2d8SCharles.Forsyth s = "-" + s; 2436*0d13e2d8SCharles.Forsyth return s; 2437*0d13e2d8SCharles.Forsyth} 2438*0d13e2d8SCharles.Forsyth 2439*0d13e2d8SCharles.Forsythprintnum(v: real, s: string) 2440*0d13e2d8SCharles.Forsyth{ 2441*0d13e2d8SCharles.Forsyth base := int pbase.val; 2442*0d13e2d8SCharles.Forsyth if(!isinteger(pbase.val) || base < 2 || base > 36) 2443*0d13e2d8SCharles.Forsyth base = 10; 2444*0d13e2d8SCharles.Forsyth sys->print("%s%s", cvt(v, base), s); 2445*0d13e2d8SCharles.Forsyth if(bits){ 2446*0d13e2d8SCharles.Forsyth r := array[1] of real; 2447*0d13e2d8SCharles.Forsyth b := array[8] of byte; 2448*0d13e2d8SCharles.Forsyth r[0] = v; 2449*0d13e2d8SCharles.Forsyth maths->export_real(b, r); 2450*0d13e2d8SCharles.Forsyth for(i := 0; i < 8; i++) 2451*0d13e2d8SCharles.Forsyth sys->print("%2.2x ", int b[i]); 2452*0d13e2d8SCharles.Forsyth sys->print("\n"); 2453*0d13e2d8SCharles.Forsyth } 2454*0d13e2d8SCharles.Forsyth} 2455*0d13e2d8SCharles.Forsyth 2456*0d13e2d8SCharles.ForsythLeft, Right, Pre, Post: con 1<<iota; 2457*0d13e2d8SCharles.Forsyth 2458*0d13e2d8SCharles.Forsythlspace := array[] of { 0, 0, 2, 3, 4, 5, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0 }; 2459*0d13e2d8SCharles.Forsythrspace := array[] of { 0, 1, 2, 3, 4, 5, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0 }; 2460*0d13e2d8SCharles.Forsyth 2461*0d13e2d8SCharles.Forsythpreced(op1: int, op2: int, s: int): int 2462*0d13e2d8SCharles.Forsyth{ 2463*0d13e2d8SCharles.Forsyth br := 0; 2464*0d13e2d8SCharles.Forsyth p1 := prec(op1); 2465*0d13e2d8SCharles.Forsyth p2 := prec(op2); 2466*0d13e2d8SCharles.Forsyth if(p1 > p2) 2467*0d13e2d8SCharles.Forsyth br = 1; 2468*0d13e2d8SCharles.Forsyth else if(p1 == p2){ 2469*0d13e2d8SCharles.Forsyth if(op1 == op2){ 2470*0d13e2d8SCharles.Forsyth if(rassoc(op1)) 2471*0d13e2d8SCharles.Forsyth br = s == Left; 2472*0d13e2d8SCharles.Forsyth else 2473*0d13e2d8SCharles.Forsyth br = s == Right && !assoc(op1); 2474*0d13e2d8SCharles.Forsyth } 2475*0d13e2d8SCharles.Forsyth else{ 2476*0d13e2d8SCharles.Forsyth if(rassoc(op1)) 2477*0d13e2d8SCharles.Forsyth br = s == Left; 2478*0d13e2d8SCharles.Forsyth else 2479*0d13e2d8SCharles.Forsyth br = s == Right && op1 != Oadd; 2480*0d13e2d8SCharles.Forsyth if(postunary(op1) && preunary(op2)) 2481*0d13e2d8SCharles.Forsyth br = 1; 2482*0d13e2d8SCharles.Forsyth } 2483*0d13e2d8SCharles.Forsyth } 2484*0d13e2d8SCharles.Forsyth return br; 2485*0d13e2d8SCharles.Forsyth} 2486*0d13e2d8SCharles.Forsyth 2487*0d13e2d8SCharles.Forsythprnode(n: ref Node) 2488*0d13e2d8SCharles.Forsyth{ 2489*0d13e2d8SCharles.Forsyth pnode(n, Onothing, Pre); 2490*0d13e2d8SCharles.Forsyth sys->print("\n"); 2491*0d13e2d8SCharles.Forsyth} 2492*0d13e2d8SCharles.Forsyth 2493*0d13e2d8SCharles.Forsythpnode(n: ref Node, opp: int, s: int) 2494*0d13e2d8SCharles.Forsyth{ 2495*0d13e2d8SCharles.Forsyth if(n == nil) 2496*0d13e2d8SCharles.Forsyth return; 2497*0d13e2d8SCharles.Forsyth op := n.op; 2498*0d13e2d8SCharles.Forsyth if(br := preced(opp, op, s)) 2499*0d13e2d8SCharles.Forsyth sys->print("("); 2500*0d13e2d8SCharles.Forsyth if(op == Oas && n.right.op >= Oadd && n.right.op <= Orsh && n.left == n.right.left){ 2501*0d13e2d8SCharles.Forsyth pnode(n.left, op, Left); 2502*0d13e2d8SCharles.Forsyth sys->print(" %s ", opstring(n.right.op+Oadde-Oadd)); 2503*0d13e2d8SCharles.Forsyth pnode(n.right.right, op, Right); 2504*0d13e2d8SCharles.Forsyth } 2505*0d13e2d8SCharles.Forsyth else if(binary(op)){ 2506*0d13e2d8SCharles.Forsyth p := prec(op); 2507*0d13e2d8SCharles.Forsyth pnode(n.left, op, Left); 2508*0d13e2d8SCharles.Forsyth if(lspace[p]) 2509*0d13e2d8SCharles.Forsyth sys->print(" "); 2510*0d13e2d8SCharles.Forsyth sys->print("%s", opstring(op)); 2511*0d13e2d8SCharles.Forsyth if(rspace[p]) 2512*0d13e2d8SCharles.Forsyth sys->print(" "); 2513*0d13e2d8SCharles.Forsyth pnode(n.right, op, Right); 2514*0d13e2d8SCharles.Forsyth } 2515*0d13e2d8SCharles.Forsyth else if(op == Oinv){ # cannot print postunary -1 2516*0d13e2d8SCharles.Forsyth sys->print("%s", opstring(op)); 2517*0d13e2d8SCharles.Forsyth pnode(n.left, Odiv, Right); 2518*0d13e2d8SCharles.Forsyth } 2519*0d13e2d8SCharles.Forsyth else if(preunary(op)){ 2520*0d13e2d8SCharles.Forsyth sys->print("%s", opstring(op)); 2521*0d13e2d8SCharles.Forsyth pnode(n.left, op, Pre); 2522*0d13e2d8SCharles.Forsyth } 2523*0d13e2d8SCharles.Forsyth else if(postunary(op)){ 2524*0d13e2d8SCharles.Forsyth pnode(n.left, op, Post); 2525*0d13e2d8SCharles.Forsyth sys->print("%s", opstring(op)); 2526*0d13e2d8SCharles.Forsyth } 2527*0d13e2d8SCharles.Forsyth else{ 2528*0d13e2d8SCharles.Forsyth case(op){ 2529*0d13e2d8SCharles.Forsyth Ostring => 2530*0d13e2d8SCharles.Forsyth sys->print("%s", n.str); 2531*0d13e2d8SCharles.Forsyth Onum => 2532*0d13e2d8SCharles.Forsyth sys->print("%g", n.val); 2533*0d13e2d8SCharles.Forsyth Ocon or 2534*0d13e2d8SCharles.Forsyth Ovar => 2535*0d13e2d8SCharles.Forsyth sys->print("%s", n.dec.sym.name); 2536*0d13e2d8SCharles.Forsyth Ofun or 2537*0d13e2d8SCharles.Forsyth Olfun => 2538*0d13e2d8SCharles.Forsyth sys->print("%s(", n.dec.sym.name); 2539*0d13e2d8SCharles.Forsyth pnode(n.left, Onothing, Pre); 2540*0d13e2d8SCharles.Forsyth sys->print(")"); 2541*0d13e2d8SCharles.Forsyth * => 2542*0d13e2d8SCharles.Forsyth fatal(sys->sprint("bad op %s in pnode()", opstring(op))); 2543*0d13e2d8SCharles.Forsyth } 2544*0d13e2d8SCharles.Forsyth } 2545*0d13e2d8SCharles.Forsyth if(br) 2546*0d13e2d8SCharles.Forsyth sys->print(")"); 2547*0d13e2d8SCharles.Forsyth} 2548