| File: | src/of_argsub.c |
| Warning: | line 743, column 2 Value stored to 'parv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /***************************************************************************** |
| 2 | * |
| 3 | * of_argsub.c: Perform function-argument substitution. |
| 4 | * |
| 5 | * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org). |
| 6 | * |
| 7 | ****************************************************************************/ |
| 8 | |
| 9 | #include "debug.h" |
| 10 | #include "of_argsub.h" |
| 11 | #include "store.h" |
| 12 | #include "util.h" |
| 13 | #include "sefo.h" |
| 14 | #include "lib.h" |
| 15 | #include "symbol.h" |
| 16 | #include "strops.h" |
| 17 | |
| 18 | /* |
| 19 | * IMPORTANT: this is code "in progress" so don't link it in yet! |
| 20 | */ |
| 21 | |
| 22 | /* |
| 23 | * argsubUnit() is the exported interface to this optimisation and |
| 24 | * is only invoked by clients not by us. |
| 25 | * |
| 26 | * agsDo*() are functions to perform argument substitution on a |
| 27 | * function or procedure call. They do not recurse. |
| 28 | * |
| 29 | * All other ags*() functions are recursive and traverse pieces |
| 30 | * of FOAM to identify the parts which can be optimised, apply |
| 31 | * the relevent agsDo* optimising function and clean up afterwards. |
| 32 | */ |
| 33 | |
| 34 | |
| 35 | /* Local helper functions - these recursively traverse FOAM */ |
| 36 | localstatic void agsDDef(Foam); |
| 37 | localstatic void agsProgram(Foam, Length); |
| 38 | localstatic void agsCompound(Foam); |
| 39 | |
| 40 | localstatic void agsCast(Foam); |
| 41 | localstatic void agsDef(Foam); |
| 42 | localstatic void agsIf(Foam); |
| 43 | localstatic void agsOCall(Foam); |
| 44 | localstatic void agsReturn(Foam); |
| 45 | localstatic void agsSeq(Foam); |
| 46 | localstatic void agsSet(Foam); |
| 47 | localstatic void agsSelect(Foam); |
| 48 | |
| 49 | |
| 50 | /* These are the crux of the module */ |
| 51 | localstatic void agsTryArgSub(Foam *, String); |
| 52 | localstatic Foam agsSubsProg(Foam, Foam *, Length, String); |
| 53 | |
| 54 | |
| 55 | /* Local helpers to answer questions about pieces of foam */ |
| 56 | localstatic Bool agsParamIsClean(Foam, AInt); |
| 57 | localstatic Bool agsFoamHasParam(Foam, AInt); |
| 58 | |
| 59 | |
| 60 | /* More local helpers - these perform argument substitutions. */ |
| 61 | localstatic Foam agsDoOCall(Foam); |
| 62 | localstatic Foam agsSubsCompound(Foam, Foam *, Length); |
| 63 | |
| 64 | |
| 65 | /* Last set of helpers which perform a variety of simple tasks */ |
| 66 | localstatic void agsAddConstant(Foam, Foam); |
| 67 | |
| 68 | |
| 69 | /* Globals to keep track of Unit/Prog information */ |
| 70 | static struct agsUnitInfoStruct agsUnitInfo; |
| 71 | static struct agsProgInfoStruct agsProgInfo; |
| 72 | |
| 73 | static AgsUnitInfo agsUnit = &agsUnitInfo; |
| 74 | static AgsProgInfo agsProg = &agsProgInfo; |
| 75 | |
| 76 | |
| 77 | /* Global lists to keep track of new Prog constants */ |
| 78 | static FoamList agsNewConsts = (FoamList)NULL((void*)0); |
| 79 | static FoamList agsNewDecls = (FoamList)NULL((void*)0); |
| 80 | static AIntList agsNewFormats = (AIntList)NULL((void*)0); |
| 81 | static Length agsNumConsts = 0; |
| 82 | |
| 83 | |
| 84 | /* Debugging flags */ |
| 85 | Bool agsDebug = false((int) 0); |
| 86 | #define agsDEBUGif (!agsDebug) { } else afprintf DEBUG_IF(ags)if (!agsDebug) { } else afprintf |
| 87 | |
| 88 | |
| 89 | /***************************************************************************** |
| 90 | * |
| 91 | * :: Exported functions |
| 92 | * |
| 93 | ****************************************************************************/ |
| 94 | |
| 95 | /* |
| 96 | * Perform argument substitutions on the whole unit. For this to work |
| 97 | * effectively the unit must have been through the optimiser so that |
| 98 | * arguments to functions are likely to be actual FOAM literals such |
| 99 | * as (SInt 42). We replace calls of the form: |
| 100 | * |
| 101 | * (Set (Loc 0 x) (OCall SInt (Const 1) (Env 0) (SInt 42))) |
| 102 | * |
| 103 | * where |
| 104 | * |
| 105 | * (Def (Const 1 foo) |
| 106 | * (Prog 0 0 SInt 4 8195 0 0 0 |
| 107 | * (DDecl Params (Decl SInt "n" -1 4)) |
| 108 | * (DDecl Locals) |
| 109 | * (DFluid) |
| 110 | * (DEnv 4 4) |
| 111 | * (Seq (Return (Par 0 n))))) |
| 112 | * |
| 113 | * into a call of the form: |
| 114 | * |
| 115 | * (Set (Loc 0 x) (OCall SInt (Const 23) (Env 0))) |
| 116 | * |
| 117 | * where (Const 23) is (Const 1) with (Par 0) replaced with (SInt 42): |
| 118 | * |
| 119 | * (Def (Const 23 foo) |
| 120 | * (Prog 0 0 SInt 4 8195 0 0 0 |
| 121 | * (DDecl Params) |
| 122 | * (DDecl Locals) |
| 123 | * (DFluid) |
| 124 | * (DEnv 4 4) |
| 125 | * (Seq (Return (SInt 42))))) |
| 126 | * |
| 127 | * For such a simple function the next iteration of the optimiser |
| 128 | * ought to inline this so that we end up with |
| 129 | * |
| 130 | * (Set (Loc 0 x) (SInt 42))) |
| 131 | * |
| 132 | * Care needs to be taken in situations where the prog being optimised |
| 133 | * has statements which treat parameters as local variables. We need |
| 134 | * to replace any references to parameters used in this way with a |
| 135 | * local variable instead. |
| 136 | */ |
| 137 | void |
| 138 | argsubUnit(Foam unit) |
| 139 | { |
| 140 | Length c; |
| 141 | |
| 142 | agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "-> argsubUnit\n"); |
| 143 | |
| 144 | |
| 145 | /* First note which unit we have ... */ |
| 146 | assert(foamTag(unit) == FOAM_Unit)do { if (!(((unit)->hdr.tag) == FOAM_Unit)) _do_assert(("foamTag(unit) == FOAM_Unit" ),"of_argsub.c",146); } while (0); |
| 147 | agsUnit->unit = unit; |
| 148 | |
| 149 | |
| 150 | /* Get information about our unit */ |
| 151 | agsUnit->fmtc = foamArgc(unit->foamUnit.formats)((unit->foamUnit.formats)->hdr.argc); |
| 152 | agsUnit->fmtv = unit->foamUnit.formats->foamDFmt.argv; |
| 153 | agsUnit->gloc = foamDDeclArgc(foamUnitGlobals(unit))(((((((unit)->foamUnit.formats)->foamGen.argv)[0].code) )->hdr.argc) - (1)); |
| 154 | agsUnit->glov = foamUnitGlobals(unit)((((unit)->foamUnit.formats)->foamGen.argv)[0].code)->foamDDecl.argv; |
| 155 | agsUnit->constc = c = foamDDeclArgc(foamUnitConstants(unit))(((((((unit)->foamUnit.formats)->foamGen.argv)[1].code) )->hdr.argc) - (1)); |
| 156 | agsUnit->constv = (Foam *) stoAlloc(OB_Other0, c*sizeof(Foam)); |
| 157 | |
| 158 | |
| 159 | /* Fill in the constant table */ |
| 160 | foamConstvFrFoam(unit, agsUnit->constc, agsUnit->constv); |
| 161 | |
| 162 | |
| 163 | /* Initially there are no new constants or formats */ |
| 164 | agsNewConsts = (FoamList)NULL((void*)0); |
| 165 | agsNewDecls = (FoamList)NULL((void*)0); |
| 166 | agsNewFormats = (AIntList)NULL((void*)0); |
| 167 | agsNumConsts = 0; |
| 168 | |
| 169 | |
| 170 | /* [debug] Initialise the agsProg structure status */ |
| 171 | agsProg->status = Uninitialised; |
| 172 | |
| 173 | |
| 174 | /* Optimise all the Defs in this unit */ |
| 175 | agsDDef(unit->foamUnit.defs); |
| 176 | |
| 177 | |
| 178 | /* Do we have to add constants to this unit? */ |
| 179 | if (agsNumConsts) |
| 180 | { |
| 181 | agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "(%d new constants)\n", |
| 182 | (int)agsNumConsts); |
| 183 | } |
| 184 | |
| 185 | |
| 186 | /* Clear up after ourselves */ |
| 187 | stoFree(agsUnit->constv); |
| 188 | agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "<- argsubUnit\n\n"); |
| 189 | } |
| 190 | |
| 191 | /***************************************************************************** |
| 192 | * |
| 193 | * :: Local helper functions. |
| 194 | * |
| 195 | ****************************************************************************/ |
| 196 | |
| 197 | /* Walk a DDef so that we can optimise each Def */ |
| 198 | localstatic void |
| 199 | agsDDef(Foam defs) |
| 200 | { |
| 201 | Length i; |
| 202 | |
| 203 | assert(foamTag(defs) == FOAM_DDef)do { if (!(((defs)->hdr.tag) == FOAM_DDef)) _do_assert(("foamTag(defs) == FOAM_DDef" ),"of_argsub.c",203); } while (0); |
| 204 | for (i = 0; i < foamArgc(defs)((defs)->hdr.argc); i++) |
| 205 | { |
| 206 | Foam def = defs->foamDDef.argv[i]; |
| 207 | Foam rhs = def->foamDef.rhs; |
| 208 | assert(foamTag(def) == FOAM_Def)do { if (!(((def)->hdr.tag) == FOAM_Def)) _do_assert(("foamTag(def) == FOAM_Def" ),"of_argsub.c",208); } while (0); |
| 209 | if (foamTag(rhs)((rhs)->hdr.tag) == FOAM_Prog) |
| 210 | agsProgram(rhs, i); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | |
| 215 | /* |
| 216 | * Now we're getting closer to the point where we can do |
| 217 | * some optimisations. We note various information about |
| 218 | * this Prog and then recurse into its body. This works |
| 219 | * because Progs can't be nested - if they can then we |
| 220 | * need to start using fluids. |
| 221 | */ |
| 222 | localstatic void |
| 223 | agsProgram(Foam prog, Length n) |
| 224 | { |
| 225 | /* Check for unexpected recursion */ |
| 226 | if (DEBUG(ags)agsDebug) { |
| 227 | switch (agsProg->status) |
| 228 | { |
| 229 | case Uninitialised: |
| 230 | break; |
| 231 | case Initialised: |
| 232 | fprintf(dbOut, "*** agsProg already initialised\n"); |
| 233 | break; |
| 234 | default: |
| 235 | fprintf(dbOut, "*** agsProg is garbage\n"); |
| 236 | break; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | |
| 241 | /* First note which prog we have ... */ |
| 242 | assert(foamTag(prog) == FOAM_Prog)do { if (!(((prog)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(prog) == FOAM_Prog" ),"of_argsub.c",242); } while (0); |
| 243 | agsProg->prog = prog; |
| 244 | agsProg->cnum = n; |
| 245 | |
| 246 | |
| 247 | /* Note the environment */ |
| 248 | agsProg->levels = prog->foamProg.levels; |
| 249 | |
| 250 | |
| 251 | /* Note the locals and parameters */ |
| 252 | agsProg->lexc = 0; |
| 253 | agsProg->lexv = (AInt *)NULL((void*)0); |
| 254 | agsProg->locc = foamDDeclArgc(prog->foamProg.locals)(((prog->foamProg.locals)->hdr.argc) - (1)); |
| 255 | agsProg->locv = prog->foamProg.locals->foamDDecl.argv; |
| 256 | agsProg->parc = foamDDeclArgc(prog->foamProg.params)(((prog->foamProg.params)->hdr.argc) - (1)); |
| 257 | agsProg->parv = prog->foamProg.params->foamDDecl.argv; |
| 258 | |
| 259 | /* Lexicals only exist if we have formats */ |
| 260 | if (agsUnit->fmtc) |
| 261 | { |
| 262 | AInt fmt = agsProg->levels->foamDEnv.argv[0]; |
| 263 | agsProg->lexc = foamDDeclArgc(agsUnit->fmtv[fmt])(((agsUnit->fmtv[fmt])->hdr.argc) - (1)); |
| 264 | agsProg->lexv = agsProg->levels->foamDEnv.argv; |
| 265 | } |
| 266 | |
| 267 | |
| 268 | /* Our structure is now initialised */ |
| 269 | if (DEBUG(ags)agsDebug) { |
| 270 | agsProg->status = Initialised; |
| 271 | } |
| 272 | |
| 273 | |
| 274 | /* Now walk over the Prog body */ |
| 275 | agsCompound(prog->foamProg.body); |
| 276 | |
| 277 | |
| 278 | /* Mark our structure as uninitialised */ |
| 279 | if (DEBUG(ags)agsDebug) { |
| 280 | agsProg->status = Uninitialised; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | |
| 285 | /* |
| 286 | * This is a generic routine to walk across a piece of FOAM |
| 287 | * that we might expect to find inside a Prog and optimise |
| 288 | * function applications by argument substitution. At the |
| 289 | * moment we only deal with OCalls but the others can be |
| 290 | * added later. |
| 291 | */ |
| 292 | localstatic void |
| 293 | agsCompound(Foam foam) |
| 294 | { |
| 295 | /* |
| 296 | * We don't need to check every possible foam tag |
| 297 | * but it's probably worth it during development. |
| 298 | */ |
| 299 | switch (foamTag(foam)((foam)->hdr.tag)) |
| 300 | { |
| 301 | /* FOAM_CONTROL nodes that we examine */ |
| 302 | case FOAM_Return: agsReturn(foam); break; |
| 303 | case FOAM_Cast: agsCast(foam); break; |
| 304 | case FOAM_Set: agsSet(foam); break; |
| 305 | case FOAM_Def: agsDef(foam); break; |
| 306 | case FOAM_If: agsIf(foam); break; |
| 307 | |
| 308 | |
| 309 | /* FOAM_NARY nodes that we examine */ |
| 310 | case FOAM_Select: agsSelect(foam); break; |
| 311 | case FOAM_OCall: agsOCall(foam); break; |
| 312 | case FOAM_Seq: agsSeq(foam); break; |
| 313 | |
| 314 | |
| 315 | /* FOAM_CONTROL nodes that we ignore */ |
| 316 | case FOAM_NOp: /* Fall through */ |
| 317 | case FOAM_BVal: /* Fall through */ |
| 318 | case FOAM_Ptr: /* Fall through */ |
| 319 | case FOAM_CProg: /* Fall through */ |
| 320 | case FOAM_CEnv: /* Fall through */ |
| 321 | case FOAM_Loose: /* Fall through */ |
| 322 | case FOAM_EEnsure: /* Fall through */ |
| 323 | case FOAM_EInfo: /* Fall through */ |
| 324 | case FOAM_Kill: /* Fall through */ |
| 325 | case FOAM_Free: /* Fall through */ |
| 326 | case FOAM_ANew: /* Fall through */ |
| 327 | case FOAM_RRNew: /* Fall through */ |
| 328 | case FOAM_RRec: /* Fall through */ |
| 329 | case FOAM_Clos: /* Fall through */ |
| 330 | case FOAM_AElt: /* Fall through */ |
| 331 | case FOAM_Goto: /* Fall through */ |
| 332 | case FOAM_Throw: /* Fall through */ |
| 333 | case FOAM_Catch: /* Fall through */ |
| 334 | case FOAM_Protect: /* Fall through */ |
| 335 | case FOAM_Unit: /* Fall through */ |
| 336 | case FOAM_PushEnv: /* Fall through */ |
| 337 | case FOAM_PopEnv: /* Fall through */ |
| 338 | case FOAM_MFmt: /* Fall through */ |
| 339 | case FOAM_RRFmt: /* Fall through */ |
| 340 | |
| 341 | |
| 342 | /* FOAM_VECTOR nodes that we ignore */ |
| 343 | case FOAM_Unimp: /* Fall through */ |
| 344 | case FOAM_GDecl: /* Fall through */ |
| 345 | case FOAM_Decl: /* Fall through */ |
| 346 | case FOAM_BInt: /* Fall through */ |
| 347 | |
| 348 | |
| 349 | /* FOAM_INDEX nodes that we ignore */ |
| 350 | case FOAM_Par: /* Fall through */ |
| 351 | case FOAM_Loc: /* Fall through */ |
| 352 | case FOAM_Glo: /* Fall through */ |
| 353 | case FOAM_Fluid: /* Fall through */ |
| 354 | case FOAM_Const: /* Fall through */ |
| 355 | case FOAM_Env: /* Fall through */ |
| 356 | case FOAM_EEnv: /* Fall through */ |
| 357 | case FOAM_RNew: /* Fall through */ |
| 358 | case FOAM_PRef: /* Fall through */ |
| 359 | case FOAM_TRNew: /* Fall through */ |
| 360 | case FOAM_RRElt: /* Fall through */ |
| 361 | case FOAM_Label: /* Fall through */ |
| 362 | |
| 363 | |
| 364 | /* FOAM_MULTINT nodes that we ignore */ |
| 365 | case FOAM_Lex: /* Fall through */ |
| 366 | case FOAM_RElt: /* Fall through */ |
| 367 | case FOAM_IRElt: /* Fall through */ |
| 368 | case FOAM_TRElt: /* Fall through */ |
| 369 | case FOAM_EElt: /* Fall through */ |
| 370 | case FOAM_CFCall: /* Fall through */ |
| 371 | case FOAM_OFCall: /* Fall through */ |
| 372 | |
| 373 | |
| 374 | /* FOAM_NARY nodes that we ignore */ |
| 375 | case FOAM_DDecl: /* Fall through */ |
| 376 | case FOAM_DFluid: /* Fall through */ |
| 377 | case FOAM_DEnv: /* Fall through */ |
| 378 | case FOAM_DDef: /* Fall through */ |
| 379 | case FOAM_DFmt: /* Fall through */ |
| 380 | case FOAM_Rec: /* Fall through */ |
| 381 | case FOAM_Arr: /* Fall through */ |
| 382 | case FOAM_TR: /* Fall through */ |
| 383 | case FOAM_PCall: /* Fall through */ |
| 384 | case FOAM_BCall: /* Fall through */ |
| 385 | case FOAM_CCall: /* Fall through */ |
| 386 | case FOAM_Values: /* Fall through */ |
| 387 | case FOAM_Prog: /* Fall through */ |
| 388 | |
| 389 | |
| 390 | /* Just ignore this case */ |
| 391 | break; |
| 392 | default : |
| 393 | /* Missing anything other than FOAM_DATA is a bug */ |
| 394 | if (foamTag(foam)((foam)->hdr.tag) >= FOAM_DATA_LIMIT) |
| 395 | bug("agsCompound: unrecognised foam"); |
| 396 | break; |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | /***************************************************************************** |
| 401 | * |
| 402 | * :: Recursive FOAM traversal functions in alphabetical order |
| 403 | * |
| 404 | ****************************************************************************/ |
| 405 | |
| 406 | localstatic void |
| 407 | agsCast(Foam foam) |
| 408 | { |
| 409 | } |
| 410 | |
| 411 | |
| 412 | localstatic void |
| 413 | agsDef(Foam foam) |
| 414 | { |
| 415 | } |
| 416 | |
| 417 | |
| 418 | localstatic void |
| 419 | agsIf(Foam foam) |
| 420 | { |
| 421 | } |
| 422 | |
| 423 | |
| 424 | localstatic void |
| 425 | agsOCall(Foam foam) |
| 426 | { |
| 427 | } |
| 428 | |
| 429 | |
| 430 | localstatic void |
| 431 | agsReturn(Foam foam) |
| 432 | { |
| 433 | } |
| 434 | |
| 435 | |
| 436 | localstatic void |
| 437 | agsSeq(Foam foam) |
| 438 | { |
| 439 | Length i; |
| 440 | Length n = foamArgc(foam)((foam)->hdr.argc); |
| 441 | |
| 442 | for (i = 0;i < n; i++) |
| 443 | agsTryArgSub(&(foamArgv(foam)((foam)->foamGen.argv)[i].code), "agsSeq"); |
| 444 | } |
| 445 | |
| 446 | |
| 447 | localstatic void |
| 448 | agsSet(Foam foam) |
| 449 | { |
| 450 | /* Sanity check (a little late perhaps!) */ |
| 451 | assert(foamTag(foam) == FOAM_Set)do { if (!(((foam)->hdr.tag) == FOAM_Set)) _do_assert(("foamTag(foam) == FOAM_Set" ),"of_argsub.c",451); } while (0); |
| 452 | |
| 453 | |
| 454 | /* Only optimise the RHS for the time being */ |
| 455 | agsTryArgSub(&(foam->foamSet.rhs), "agsSet"); |
| 456 | } |
| 457 | |
| 458 | |
| 459 | localstatic void |
| 460 | agsSelect(Foam foam) |
| 461 | { |
| 462 | } |
| 463 | |
| 464 | |
| 465 | /***************************************************************************** |
| 466 | * |
| 467 | * :: The following calls actually perform the argument substitutions |
| 468 | * |
| 469 | ****************************************************************************/ |
| 470 | |
| 471 | /* |
| 472 | * Given a pointer to a piece of FOAM, see if we can replace |
| 473 | * it with a similar piece that has been optimised. |
| 474 | */ |
| 475 | localstatic void |
| 476 | agsTryArgSub(Foam *ptr, String fun) |
| 477 | { |
| 478 | Foam elt = *ptr; |
| 479 | Foam new = elt; |
| 480 | |
| 481 | /* |
| 482 | * Recurse into the node. This may modify deeper |
| 483 | * nodes or leaves but we don't mind. |
| 484 | */ |
| 485 | agsCompound(elt); |
| 486 | |
| 487 | |
| 488 | /* |
| 489 | * Check to see if we have something that |
| 490 | * can have its arguments substituted. |
| 491 | */ |
| 492 | switch (foamTag(elt)((elt)->hdr.tag)) |
| 493 | { |
| 494 | case FOAM_OCall: |
| 495 | new = agsDoOCall(elt); |
| 496 | break; |
| 497 | default: |
| 498 | break; |
| 499 | } |
| 500 | |
| 501 | |
| 502 | /* Did a substitution take place? */ |
| 503 | if (new != elt) |
| 504 | { |
| 505 | /* Yes - modify the FOAM */ |
| 506 | /* Show what happened */ |
| 507 | if (DEBUG(ags)agsDebug) { |
| 508 | (void)fprintf(dbOut, "** %s substitution\n", fun); |
| 509 | (void)fprintf(dbOut, ">>\n"); |
| 510 | foamPrintDb(elt); |
| 511 | (void)fprintf(dbOut, "<<\n"); |
| 512 | foamPrintDb(new); |
| 513 | (void)fprintf(dbOut, "\n"); |
| 514 | } |
| 515 | |
| 516 | foamFreeNode(elt); |
| 517 | *ptr = new; |
| 518 | } |
| 519 | } |
| 520 | |
| 521 | |
| 522 | /* |
| 523 | * Given an OCall, perform any argument substitutions that are |
| 524 | * possible and allowed. We return a new OCall to replace the |
| 525 | * original one. Note that we don't recurse into the OCall as |
| 526 | * this has already been done at a higher level. |
| 527 | */ |
| 528 | localstatic Foam |
| 529 | agsDoOCall(Foam foam) |
| 530 | { |
| 531 | Foam op, body, new; |
| 532 | Length i, argc, rargc, nargc; |
| 533 | Syme opSyme; |
| 534 | UShort cnum; |
| 535 | Bool isLocal; |
| 536 | Foam *sigma; |
| 537 | |
| 538 | |
| 539 | /* Safety check */ |
| 540 | assert(foamTag(foam) == FOAM_OCall)do { if (!(((foam)->hdr.tag) == FOAM_OCall)) _do_assert(("foamTag(foam) == FOAM_OCall" ),"of_argsub.c",540); } while (0); |
| 541 | |
| 542 | |
| 543 | /* What do we have here? */ |
| 544 | argc = foamArgc(foam)((foam)->hdr.argc); |
| 545 | op = foam->foamOCall.op; |
| 546 | |
| 547 | |
| 548 | /* Get the symbol meaning associated with op */ |
| 549 | opSyme = foamSyme(op)((op)->hdr.syme); |
| 550 | if (!opSyme) |
| 551 | return foam; |
| 552 | |
| 553 | |
| 554 | /* We can only handle constants */ |
| 555 | if (!genHasConstNum(opSyme)) |
| 556 | return foam; |
| 557 | |
| 558 | |
| 559 | /* Get the constant number for this operator */ |
| 560 | cnum = genGetConstNum(opSyme); |
| 561 | |
| 562 | |
| 563 | /* Is this a local or a library operator? */ |
| 564 | isLocal = symeIsLocalConst(opSyme)(symeConstLib(opSyme) == ((void*)0)); |
| 565 | if (isLocal) |
| 566 | { |
| 567 | assert(cnum < agsUnit->constc)do { if (!(cnum < agsUnit->constc)) _do_assert(("cnum < agsUnit->constc" ),"of_argsub.c",567); } while (0); |
| 568 | body = agsUnit->constv[cnum]; |
| 569 | } |
| 570 | else |
| 571 | { |
| 572 | Lib origin = symeConstLib(opSyme); |
| 573 | body = libGetFoamConstant(origin, cnum); |
| 574 | } |
| 575 | |
| 576 | |
| 577 | /* More sanity checks */ |
| 578 | assert(body)do { if (!(body)) _do_assert(("body"),"of_argsub.c",578); } while (0); |
| 579 | assert(foamTag(body) == FOAM_Prog)do { if (!(((body)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(body) == FOAM_Prog" ),"of_argsub.c",579); } while (0); |
| 580 | |
| 581 | |
| 582 | /* Display what we've got here */ |
| 583 | if (DEBUG(ags)agsDebug) { |
| 584 | (void)fprintf(dbOut,"** agsDoOCall: "); |
| 585 | (void)symePrintDb(opSyme); |
| 586 | |
| 587 | for (i = 3;i < argc;i++) |
| 588 | { |
| 589 | Foam arg = foamArgv(foam)((foam)->foamGen.argv)[i].code; |
| 590 | Syme syme = foamSyme(arg)((arg)->hdr.syme); |
| 591 | |
| 592 | (void)fprintf(dbOut," Arg: "); |
| 593 | if (syme) |
| 594 | (void)symePrintDb(syme); |
| 595 | else |
| 596 | (void)foamPrintDb(arg); |
| 597 | } |
| 598 | (void)fprintf(dbOut,"\n"); |
| 599 | } |
| 600 | |
| 601 | |
| 602 | /* How many arguments are we giving this function? */ |
| 603 | rargc = argc - 3; |
| 604 | assert(rargc == agsProg->parc)do { if (!(rargc == agsProg->parc)) _do_assert(("rargc == agsProg->parc" ),"of_argsub.c",604); } while (0); |
| 605 | |
| 606 | |
| 607 | /* |
| 608 | * Decide which arguments need changing. We do this |
| 609 | * by creating an array of substitutions, with one |
| 610 | * slot for each parameter in order. Parameters which |
| 611 | * are not substituted are initialised to their actual |
| 612 | * foam par number. |
| 613 | */ |
| 614 | sigma = (Foam *)stoAlloc(OB_Other0, rargc*sizeof(Foam)); |
| 615 | nargc = 0; |
| 616 | for (i = 3; i < argc; i++) |
| 617 | { |
| 618 | Foam nocast; |
| 619 | Foam arg = foamArgv(foam)((foam)->foamGen.argv)[i].code; |
| 620 | |
| 621 | /* Strip off any cast */ |
| 622 | if (foamTag(arg)((arg)->hdr.tag) == FOAM_Cast) |
| 623 | nocast = arg->foamCast.expr; |
| 624 | else |
| 625 | nocast = arg; |
| 626 | |
| 627 | |
| 628 | /* Can we do any substitutions? */ |
| 629 | if (foamTag(nocast)((nocast)->hdr.tag) == FOAM_SInt) |
| 630 | { |
| 631 | /* Only if this param is clean */ |
| 632 | if (agsParamIsClean(body, i-3)) |
| 633 | { |
| 634 | sigma[i-3] = arg; |
| 635 | continue; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | |
| 640 | /* Remap the parameter */ |
| 641 | sigma[i-3] = foamNewPar(nargc)foamNew(FOAM_Par, 1, (AInt)(nargc)); |
| 642 | nargc++; |
| 643 | } |
| 644 | |
| 645 | if (DEBUG(ags)agsDebug) { |
| 646 | for (i = 0; i < rargc; i++) |
| 647 | { |
| 648 | (void)fprintf(dbOut, " [%d] = ", (int)i); |
| 649 | foamPrintDb(sigma[i]); |
| 650 | } |
| 651 | } |
| 652 | |
| 653 | |
| 654 | /* |
| 655 | * Do the substitution - this gives us a new function |
| 656 | * to call which we need to add to the unit and then |
| 657 | * call correctly using the new signature. |
| 658 | */ |
| 659 | new = agsSubsProg(body, sigma, rargc, symString(symeId(opSyme))((((opSyme)->id))->str)); |
| 660 | |
| 661 | |
| 662 | /* Clean up after ourselves */ |
| 663 | stoFree(sigma); |
| 664 | return foam; |
| 665 | } |
| 666 | |
| 667 | |
| 668 | /* |
| 669 | * Return `true' if the specified parameter never appears on the LHS |
| 670 | * of a set/assignment otherwise return `false'. Clean parameters |
| 671 | * are those which aren't used as local variables. |
| 672 | */ |
| 673 | localstatic Bool |
| 674 | agsParamIsClean(Foam body, AInt param) |
| 675 | { |
| 676 | assert(body)do { if (!(body)) _do_assert(("body"),"of_argsub.c",676); } while (0); |
| 677 | |
| 678 | |
| 679 | /* Base case - we are looking for a foamSet node */ |
| 680 | if (foamTag(body)((body)->hdr.tag) == FOAM_Set) |
| 681 | { |
| 682 | /* |
| 683 | * Does this foamPar appear on the LHS of the |
| 684 | * foamSet. If it does then it is probably being |
| 685 | * used as a local variable which is naughty. |
| 686 | */ |
| 687 | if (agsFoamHasParam(body->foamSet.lhs, param)) |
| 688 | return false((int) 0); |
| 689 | } |
| 690 | |
| 691 | |
| 692 | /* Check each sub-node */ |
| 693 | foamIter(body, arg,{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv )+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0) ; }; }; } } }; } |
| 694 | {{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv )+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0) ; }; }; } } }; } |
| 695 | if (!agsParamIsClean(*arg, param)){ { String argf = (foamInfoTable [(int)(((body)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv )+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0) ; }; }; } } }; } |
| 696 | return false;{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv )+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0) ; }; }; } } }; } |
| 697 | }){ { String argf = (foamInfoTable [(int)(((body)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv )+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0) ; }; }; } } }; }; |
| 698 | |
| 699 | return true1; |
| 700 | } |
| 701 | |
| 702 | |
| 703 | /* |
| 704 | * Returns `true' if the foam contains a reference to the |
| 705 | * parameter `param'. This is probably too restrictive since |
| 706 | * it may be possible for a (Par n) to appear on the LHS of |
| 707 | * a foamSet and not be modified. However, the optimiser is |
| 708 | * probably going to flatten the LHS anyway and if the node |
| 709 | * is read-only then we will get to optimise it next time. |
| 710 | */ |
| 711 | localstatic Bool |
| 712 | agsFoamHasParam(Foam foam, AInt param) |
| 713 | { |
| 714 | assert(foam)do { if (!(foam)) _do_assert(("foam"),"of_argsub.c",714); } while (0); |
| 715 | |
| 716 | |
| 717 | /* Base case - we want a foamPar */ |
| 718 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_Par) |
| 719 | return (foam->foamPar.index == param); |
| 720 | |
| 721 | |
| 722 | /* Check each sub-node */ |
| 723 | foamIter(foam, arg,{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; } } }; } |
| 724 | {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; } } }; } |
| 725 | if (agsFoamHasParam(*arg, param)){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; } } }; } |
| 726 | return true;{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; } } }; } |
| 727 | }){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; } } }; }; |
| 728 | |
| 729 | return false((int) 0); |
| 730 | } |
| 731 | |
| 732 | |
| 733 | localstatic Foam |
| 734 | agsSubsProg(Foam foam, Foam *sigma, Length argc, String name) |
| 735 | { |
| 736 | Foam prog, decl; |
| 737 | Foam *parv; |
| 738 | Length parc; |
| 739 | |
| 740 | |
| 741 | /* Pull out the list of function parameters */ |
| 742 | parc = foamDDeclArgc(foam->foamProg.params)(((foam->foamProg.params)->hdr.argc) - (1)); |
| 743 | parv = foam->foamProg.params->foamDDecl.argv; |
Value stored to 'parv' is never read | |
| 744 | |
| 745 | /* Create a new prog */ |
| 746 | prog = foamNewProgfoamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 747 | (foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 748 | /* Leading fields accessed anonymously */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 749 | foam->foamGen.argv[0].data, /* endOffset */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 750 | foam->foamGen.argv[1].data, /* nLabels */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 751 | foam->foamGen.argv[2].data, /* retType */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 752 | foam->foamGen.argv[3].data, /* format */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 753 | foam->foamGen.argv[4].data, /* infoBits */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 754 | NULL, /* (Foam)params */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 755 | foamCopy(foam->foamProg.locals),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 756 | foamCopy(foam->foamProg.fluids),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 757 | foamCopy(foam->foamProg.levels),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 758 | NULL /* body */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)) |
| 759 | )foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data), (AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen .argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)( foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , ( (void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam-> foamProg.fluids), foamCopy(foam->foamProg.levels), ((void* )0)); |
| 760 | |
| 761 | /* Create a declaration for this prog */ |
| 762 | decl = foamNewDecl(FOAM_Prog, strCopy(name), emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(FOAM_Prog),strCopy(name), (AInt) ( 0x7FFF), 4); |
| 763 | |
| 764 | |
| 765 | /* Add this prog to the list of new constants */ |
| 766 | agsAddConstant(prog, decl); |
| 767 | |
| 768 | |
| 769 | /* Perform the substitutions on the function body. */ |
| 770 | prog->foamProg.body = agsSubsCompound(foam->foamProg.body, sigma, argc); |
| 771 | |
| 772 | |
| 773 | /* Patch up the parameter list */ |
| 774 | /* prog->params = ... */ |
| 775 | prog->foamProg.params = foam->foamProg.params; /* WRONG!!!! */ |
| 776 | |
| 777 | |
| 778 | /* Perhaps we ought to sort out the size and execution times? */ |
| 779 | |
| 780 | |
| 781 | /* Return the new const */ |
| 782 | return prog; |
| 783 | } |
| 784 | |
| 785 | |
| 786 | /* |
| 787 | * Copy a piece of foam substituting each (Par i) with sigma[i] |
| 788 | */ |
| 789 | localstatic Foam |
| 790 | agsSubsCompound(Foam foam, Foam *sigma, Length argc) |
| 791 | { |
| 792 | Foam new; |
| 793 | |
| 794 | assert(foam)do { if (!(foam)) _do_assert(("foam"),"of_argsub.c",794); } while (0); |
| 795 | |
| 796 | |
| 797 | /* Create a new node sharing original storage */ |
| 798 | new = foamCopyNode(foam); |
| 799 | |
| 800 | |
| 801 | /* Base case - deal with foamPar nodes */ |
| 802 | if (foamTag(foam)((foam)->hdr.tag) == FOAM_Par) |
| 803 | { |
| 804 | assert(foam->foamPar.index < argc)do { if (!(foam->foamPar.index < argc)) _do_assert(("foam->foamPar.index < argc" ),"of_argsub.c",804); } while (0); |
| 805 | return foamCopy(sigma[foam->foamPar.index]); |
| 806 | } |
| 807 | |
| 808 | |
| 809 | /* Recurse into nodes overwriting shared storage */ |
| 810 | foamIter(foam, arg,{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } } }; } |
| 811 | {{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } } }; } |
| 812 | *arg = agsSubsCompound(*arg, sigma, argc);{ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } } }; } |
| 813 | }){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag)) -(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam )->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv )+_i; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } } }; }; |
| 814 | |
| 815 | |
| 816 | /* Return the modified foam */ |
| 817 | return new; |
| 818 | } |
| 819 | |
| 820 | |
| 821 | localstatic void |
| 822 | agsAddConstant(Foam foam, Foam decl) |
| 823 | { |
| 824 | agsNewConsts = listCons(Foam)(Foam_listPointer->Cons)(foam, agsNewConsts); |
| 825 | agsNewDecls = listCons(Foam)(Foam_listPointer->Cons)(decl, agsNewConsts); |
| 826 | agsNumConsts++; |
| 827 | } |
| 828 | |
| 829 |