| File: | src/gf_gener.c |
| Warning: | line 328, column 2 Value stored to 'type' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /***************************************************************************** |
| 2 | * |
| 3 | * gf_gener.c: Foam code generation for generators. |
| 4 | * |
| 5 | * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org). |
| 6 | * |
| 7 | ****************************************************************************/ |
| 8 | |
| 9 | #include "fluid.h" |
| 10 | #include "genfoam.h" |
| 11 | #include "gf_util.h" |
| 12 | #include "gf_prog.h" |
| 13 | #include "gf_gener.h" |
| 14 | #include "of_inlin.h" |
| 15 | #include "of_util.h" |
| 16 | #include "optinfo.h" |
| 17 | #include "store.h" |
| 18 | #include "tform.h" |
| 19 | #include "comsg.h" |
| 20 | #include "util.h" |
| 21 | |
| 22 | #define GenerBetterGuesses |
| 23 | |
| 24 | typedef struct GenBoundCalc *GenBoundCalc; |
| 25 | typedef struct GenerGenInfo *GenerGenInfo; |
| 26 | |
| 27 | localstatic Foam gen0GenerBodyFun (AbSyn, TForm); |
| 28 | localstatic Foam gen0GenerSelect (int); |
| 29 | localstatic Foam gen0GenerDoneFun (void); |
| 30 | localstatic Foam gen0GenerStepFun (AbSyn, TForm); |
| 31 | localstatic Foam gen0GenerValueFun (FoamTag, TForm); |
| 32 | localstatic Foam gen0GenerBoundFun (AbSyn, GenBoundCalc); |
| 33 | localstatic Foam gen0MakeGenerVars (TForm); |
| 34 | localstatic Foam gen0GetGenerVar (Foam env, int id); |
| 35 | |
| 36 | #ifdef GenerBetterGuesses |
| 37 | localstatic GenBoundCalc gen0MakeBoundInit(AbSyn); |
| 38 | localstatic Foam gen0ComputeBoundFunction(GenBoundCalc); |
| 39 | localstatic void gen0ComputeGeners(void); |
| 40 | #endif |
| 41 | |
| 42 | static Foam gen0GenVars; |
| 43 | static GenerGenInfo gen0GenInfo; |
| 44 | |
| 45 | #define gen0RetFormatSize4 4 |
| 46 | static String gen0RetFormatNames[] = { "done?", "step!", "value", "bound" }; |
| 47 | static FoamTag gen0RetFormatTypes[] = { FOAM_Clos, FOAM_Clos, FOAM_Clos, FOAM_Clos }; |
| 48 | static AInt gen0RetFormatFmts[] = { emptyFormatSlot4, emptyFormatSlot4, |
| 49 | emptyFormatSlot4, emptyFormatSlot4}; |
| 50 | |
| 51 | #define yieldDoneLoc0 0 |
| 52 | #define yieldPlaceLoc1 1 |
| 53 | #define yieldValueLoc2 2 |
| 54 | |
| 55 | #define yieldDoneVargen0GetGenerVar(gen0GenVars, 0) gen0GetGenerVar(gen0GenVars, yieldDoneLoc0) |
| 56 | #define yieldPlaceVargen0GetGenerVar(gen0GenVars, 1) gen0GetGenerVar(gen0GenVars, yieldPlaceLoc1) |
| 57 | #define yieldValVargen0GetGenerVar(gen0GenVars, 2) gen0GetGenerVar(gen0GenVars, yieldValueLoc2) |
| 58 | |
| 59 | #define stepperFName()("generStepper") ("generStepper") |
| 60 | #define doneFName()("generDone?") ("generDone?") |
| 61 | #define boundFName()("generBound") ("generBound") |
| 62 | #define valueFName()("generValue") ("generValue") |
| 63 | |
| 64 | #define boundPlace3 3 |
| 65 | |
| 66 | /* |
| 67 | * Generate code for a yield. |
| 68 | */ |
| 69 | |
| 70 | Foam |
| 71 | gen0Yield(AbSyn absyn) |
| 72 | { |
| 73 | /* set the place variable */ |
| 74 | gen0AddStmt(foamNewSet(yieldPlaceVar,foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 1), foamNew (FOAM_SInt, 1, (AInt)(++gen0State->yieldCount))) |
| 75 | foamNewSInt(++gen0State->yieldCount))foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 1), foamNew (FOAM_SInt, 1, (AInt)(++gen0State->yieldCount))), absyn); |
| 76 | gen0AddStmt(foamNewSet(foamCopy(gen0State->yieldValueVar),foamNew(FOAM_Set, 2, foamCopy(gen0State->yieldValueVar), genFoamVal (absyn->abYield.value)) |
| 77 | genFoamVal(absyn->abYield.value))foamNew(FOAM_Set, 2, foamCopy(gen0State->yieldValueVar), genFoamVal (absyn->abYield.value)), absyn); |
| 78 | gen0AddStmt(foamNewGoto(gen0State->yieldPlace)foamNew(FOAM_Goto, 1, (AInt)(gen0State->yieldPlace)), absyn); |
| 79 | |
| 80 | gen0AddStmt(foamNewLabel(gen0State->labelNo)foamNew(FOAM_Label, 1, (AInt)(gen0State->labelNo)), absyn); |
| 81 | gen0State->yieldLabels = listCons(AInt)(AInt_listPointer->Cons)(gen0State->labelNo++, |
| 82 | gen0State->yieldLabels); |
| 83 | return 0; |
| 84 | } |
| 85 | |
| 86 | /* |
| 87 | * Generate a generator body (a body containing yields) |
| 88 | */ |
| 89 | |
| 90 | Foam |
| 91 | gen0Generate(AbSyn iter) |
| 92 | { |
| 93 | foamProgUnsetLeaf(gen0State->program)((gen0State->program)->foamProg.infoBits &= ~(1 << 1)); |
| 94 | return gen0GenerBodyFun(iter, tfGeneratorArg(gen0AbType(iter))tfFollowArg(gen0AbType(iter), 0)); |
| 95 | } |
| 96 | |
| 97 | /* |
| 98 | * generate the code for the first level of a generator function. |
| 99 | */ |
| 100 | |
| 101 | localstatic Foam |
| 102 | gen0GenerBodyFun(AbSyn iter, TForm tf) |
| 103 | { |
| 104 | Scope("genBody0")String scopeName = ("genBody0"); int fluidLevel0 = (scopeLevel ++, fluidLevel); |
| 105 | FoamList topLines; |
| 106 | Bool flag; |
| 107 | GenerGenInfo fluid(gen0GenInfo)fluidSave_gen0GenInfo = ( fluidStack = (fluidLevel==fluidLimit ) ? fluidGrow() : fluidStack, fluidStack[fluidLevel].scopeName = scopeName, fluidStack[fluidLevel].scopeLevel = scopeLevel, fluidStack[fluidLevel].pglobal = (Pointer) &(gen0GenInfo ), fluidStack[fluidLevel].pstack = (Pointer) &fluidSave_gen0GenInfo , fluidStack[fluidLevel].size = sizeof(gen0GenInfo), fluidLevel ++, (gen0GenInfo) ); |
| 108 | GenBoundCalc calc = NULL((void*)0); |
| 109 | AbSyn body = iter->abGenerate.body; |
| 110 | AbSyn bound = iter->abGenerate.count; |
| 111 | FoamTag retType = gen0Type(tf, NULL((void*)0)); |
| 112 | Foam fluid(gen0GenVars)fluidSave_gen0GenVars = ( fluidStack = (fluidLevel==fluidLimit ) ? fluidGrow() : fluidStack, fluidStack[fluidLevel].scopeName = scopeName, fluidStack[fluidLevel].scopeLevel = scopeLevel, fluidStack[fluidLevel].pglobal = (Pointer) &(gen0GenVars ), fluidStack[fluidLevel].pstack = (Pointer) &fluidSave_gen0GenVars , fluidStack[fluidLevel].size = sizeof(gen0GenVars), fluidLevel ++, (gen0GenVars) ); |
| 113 | |
| 114 | GenFoamState saved; |
| 115 | Foam foam, clos, stmt; |
| 116 | Foam done, step, bnd, value; |
| 117 | |
| 118 | gen0GenInfo = NULL((void*)0); |
| 119 | #ifdef GenerBetterGuesses |
| 120 | if (!bound || abTag(bound)((bound)->abHdr.tag) == AB_Nothing) { |
| 121 | calc = gen0MakeBoundInit(body); |
| 122 | gen0ComputeGeners(); |
| 123 | } |
| 124 | #endif |
| 125 | flag = gen0AddImportPlace(&topLines); |
| 126 | |
| 127 | clos = gen0ProgClosEmpty(); |
| 128 | foam = gen0ProgInitEmpty("generBaseFn", body); |
| 129 | |
| 130 | saved = gen0ProgSaveState(PT_Gener); |
| 131 | |
| 132 | gen0GenVars = gen0MakeGenerVars(tf); |
| 133 | |
| 134 | step = gen0GenerStepFun(body, tf); |
| 135 | done = gen0GenerDoneFun(); |
| 136 | value = gen0GenerValueFun(retType, tf); |
| 137 | bnd = gen0GenerBoundFun(bound, calc); |
| 138 | |
| 139 | stmt = foamNewReturn(foamNew(FOAM_Values, 4, done, step, value, bnd))foamNew(FOAM_Return, 1, foamNew(FOAM_Values, 4, done, step, value , bnd)); |
| 140 | gen0AddStmt(stmt, body); |
| 141 | |
| 142 | gen0UseStackedFormat(int0((int) 0)); |
| 143 | gen0ProgPushFormat(int0((int) 0)); |
| 144 | gen0ProgFiniEmpty(foam, FOAM_NOp, int0((int) 0)); |
| 145 | foam->foamProg.format = gen0MakeGenerRetFormat(); |
| 146 | |
| 147 | gen0AddLexLevels(foam, 1); |
| 148 | |
| 149 | foam->foamProg.infoBits = IB_SIDE(1 << 0) | IB_INLINEME(1 << 4); |
| 150 | foamOptInfo(foam)((foam)->hdr.info.opt) = optInfoNew(NULL((void*)0), foam, NULL((void*)0), false((int) 0)); |
| 151 | |
| 152 | if (gen0GenInfo) stoFree(gen0GenInfo); |
| 153 | |
| 154 | gen0ProgRestoreState(saved); |
| 155 | |
| 156 | if (flag) gen0ResetImportPlace(topLines); |
| 157 | |
| 158 | stmt = foamNewSet(yieldPlaceVar, foamNewSInt(int0))foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 1), foamNew (FOAM_SInt, 1, (AInt)(((int) 0)))); |
| 159 | gen0AddStmt(stmt, iter); |
| 160 | |
| 161 | foamFree(gen0GenVars); |
| 162 | gen0GenVars = NULL((void*)0); |
| 163 | |
| 164 | Return(clos){ fluidUnwind(fluidLevel0, ((int) 0)); return clos;; }; |
| 165 | } |
| 166 | |
| 167 | /* |
| 168 | * Generate the code for the second level of a generator function. |
| 169 | */ |
| 170 | |
| 171 | localstatic Foam |
| 172 | gen0GenerStepFun(AbSyn body, TForm tf) |
| 173 | { |
| 174 | GenFoamState saved; |
| 175 | Foam foam, clos, tmp; |
| 176 | FoamTag yieldType; |
| 177 | AInt startLabel; |
| 178 | AInt fmtSlot; |
| 179 | clos = foamNewClos(foamNewEnv(-1), foamNewConst(gen0NumProgs))foamNew(FOAM_Clos,2, foamNew(FOAM_Env, 1, (AInt)(-1)), foamNew (FOAM_Const, 1, (AInt)(gen0NumProgs))); |
| 180 | foam = gen0ProgInitEmpty(stepperFName()("generStepper"), body); |
| 181 | |
| 182 | saved = gen0ProgSaveState(PT_Gener); |
| 183 | |
| 184 | startLabel = gen0State->labelNo++; |
| 185 | gen0State->yieldPlace = gen0State->labelNo++; |
| 186 | |
| 187 | tf = tfDefineeType(tf); |
| 188 | yieldType = gen0Type(tf, &fmtSlot); |
| 189 | |
| 190 | gen0State->yieldValueVar = gen0TempLocal0(yieldType, fmtSlot); |
| 191 | |
| 192 | tmp = foamNewNOp()foamNew(FOAM_NOp, (int) 0); |
| 193 | gen0AddStmt(tmp, NULL((void*)0)); /* filled by gen0GenerSelect */ |
| 194 | gen0AddStmt(foamNewLabel(startLabel)foamNew(FOAM_Label, 1, (AInt)(startLabel)), NULL((void*)0)); |
| 195 | gen0AddStmt(foamNewSet(yieldDoneVar, foamNewBool(int0))foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 0), foamNew (FOAM_Bool, 1, (AInt)(((int) 0)))), NULL((void*)0)); |
| 196 | genFoamStmt(body); |
| 197 | gen0AddStmt(foamNewSet(yieldDoneVar, foamNewBool(1))foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 0), foamNew (FOAM_Bool, 1, (AInt)(1))), NULL((void*)0)); |
| 198 | gen0AddStmt(foamNewReturn(foamNew(FOAM_Values, int0))foamNew(FOAM_Return, 1, foamNew(FOAM_Values, ((int) 0))), NULL((void*)0)); |
| 199 | gen0AddStmt(foamNewLabel(gen0State->yieldPlace)foamNew(FOAM_Label, 1, (AInt)(gen0State->yieldPlace)), NULL((void*)0)); |
| 200 | gen0AddStmt(foamNewSet(yieldValVar, gen0State->yieldValueVar)foamNew(FOAM_Set, 2, gen0GetGenerVar(gen0GenVars, 2), gen0State ->yieldValueVar), NULL((void*)0)); |
| 201 | gen0AddStmt(foamNewReturn(foamNew(FOAM_Values, int0))foamNew(FOAM_Return, 1, foamNew(FOAM_Values, ((int) 0))), NULL((void*)0)); |
| 202 | |
| 203 | gen0UseStackedFormat(int0((int) 0)); |
| 204 | gen0ProgPushFormat(emptyFormatSlot4); |
| 205 | gen0ProgPushFormat(emptyFormatSlot4); |
| 206 | gen0ProgFiniEmpty(foam, FOAM_NOp, int0((int) 0)); |
| 207 | |
| 208 | /* fill in the select statement */ |
| 209 | foam->foamProg.body->foamSeq.argv[0] = gen0GenerSelect(startLabel); |
| 210 | foamFree(tmp); |
| 211 | gen0AddLexLevels(foam, 2); |
| 212 | |
| 213 | foam->foamProg.infoBits = IB_SIDE(1 << 0) | IB_INLINEME(1 << 4); |
| 214 | foamOptInfo(foam)((foam)->hdr.info.opt) = optInfoNew(gen0State->stab, foam, NULL((void*)0), true1); |
| 215 | |
| 216 | gen0ProgRestoreState(saved); |
| 217 | return clos; |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | * Generate the select statement for generator body dispatching. |
| 222 | */ |
| 223 | |
| 224 | localstatic Foam |
| 225 | gen0GenerSelect(int startLabel) |
| 226 | { |
| 227 | Foam select = foamNewEmpty(FOAM_Select, gen0State->yieldCount+2); |
| 228 | int i; |
| 229 | |
| 230 | select->foamSelect.op = yieldPlaceVargen0GetGenerVar(gen0GenVars, 1); |
| 231 | gen0State->yieldLabels = listNReverse(AInt)(AInt_listPointer->NReverse)(gen0State->yieldLabels); |
| 232 | select->foamSelect.argv[0] = startLabel; |
| 233 | for(i=1; |
| 234 | i <= gen0State->yieldCount; |
| 235 | i++, gen0State->yieldLabels = cdr(gen0State->yieldLabels)((gen0State->yieldLabels)->rest)) |
| 236 | select->foamSelect.argv[i] = car(gen0State->yieldLabels)((gen0State->yieldLabels)->first); |
| 237 | return select; |
| 238 | } |
| 239 | |
| 240 | /* |
| 241 | * Make the lexical environment for a generator. |
| 242 | */ |
| 243 | |
| 244 | localstatic Foam |
| 245 | gen0MakeGenerVars(TForm retType) |
| 246 | { |
| 247 | Foam done, place, value; |
| 248 | FoamTag type; |
| 249 | AInt fmt; |
| 250 | |
| 251 | done = gen0Temp(FOAM_Bool)gen0Temp0(FOAM_Bool, 4); |
| 252 | place = gen0Temp(FOAM_SInt)gen0Temp0(FOAM_SInt, 4); |
| 253 | /* multi-valued gens not supported yet */ |
| 254 | type = gen0Type(retType, &fmt); |
| 255 | assert(!tfIsMulti(retType))do { if (!(!(((retType)->tag) == TF_Multiple))) _do_assert (("!tfIsMulti(retType)"),"gf_gener.c",255); } while (0); |
| 256 | value = gen0Temp0(type, fmt); |
| 257 | |
| 258 | return foamNew(FOAM_Values, 3, done, place, value); |
| 259 | } |
| 260 | |
| 261 | localstatic Foam |
| 262 | gen0GetGenerVar(Foam env, int id) |
| 263 | { |
| 264 | return foamCopy(env->foamValues.argv[id]); |
| 265 | } |
| 266 | |
| 267 | AInt |
| 268 | gen0MakeGenerRetFormat() |
| 269 | { |
| 270 | if (gen0GenerRetFormat) return gen0GenerRetFormat; |
| 271 | |
| 272 | gen0GenerRetFormat = gen0StdDeclFormat(gen0RetFormatSize4, gen0RetFormatNames, |
| 273 | gen0RetFormatTypes, gen0RetFormatFmts); |
| 274 | gen0SetDDeclUsage(gen0GenerRetFormat, FOAM_DDecl_Multi); |
| 275 | return gen0GenerRetFormat; |
| 276 | } |
| 277 | |
| 278 | localstatic Foam |
| 279 | gen0GenerDoneFun() |
| 280 | { |
| 281 | return gen0BuildFunFromFoam(doneFName()("generDone?"), FOAM_Bool, yieldDoneVargen0GetGenerVar(gen0GenVars, 0)); |
| 282 | } |
| 283 | |
| 284 | localstatic Foam |
| 285 | gen0GenerBoundFun(AbSyn bound, GenBoundCalc calc) |
| 286 | { |
| 287 | if (calc) |
| 288 | return gen0ComputeBoundFunction(calc); |
| 289 | else if (!bound || abTag(bound)((bound)->abHdr.tag) == AB_Nothing) |
| 290 | return gen0BuildFunFromFoam(boundFName()("generBound"), FOAM_SInt, |
| 291 | foamNewSInt(-1)foamNew(FOAM_SInt, 1, (AInt)(-1))); |
| 292 | else { |
| 293 | GenFoamState saved; |
| 294 | Foam foam, clos, ret; |
| 295 | |
| 296 | clos = foamNewClos(foamNewEnv(-1), foamNewConst(gen0NumProgs))foamNew(FOAM_Clos,2, foamNew(FOAM_Env, 1, (AInt)(-1)), foamNew (FOAM_Const, 1, (AInt)(gen0NumProgs))); |
| 297 | foam = gen0ProgInitEmpty(boundFName()("generBound"), bound); |
| 298 | |
| 299 | saved = gen0ProgSaveState(PT_ExFn); |
| 300 | |
| 301 | ret = genFoamVal(bound); |
| 302 | if (ret) gen0AddStmt(foamNewReturn(ret)foamNew(FOAM_Return, 1, ret), bound); |
| 303 | |
| 304 | gen0UseStackedFormat(int0((int) 0)); |
| 305 | gen0ProgPushFormat(emptyFormatSlot4); |
| 306 | gen0ProgPushFormat(emptyFormatSlot4); |
| 307 | gen0ProgFiniEmpty(foam, gen0Type(gen0AbType(bound), NULL((void*)0)), int0((int) 0)); |
| 308 | |
| 309 | gen0AddLexLevels(foam, 2); |
| 310 | |
| 311 | foamOptInfo(foam)((foam)->hdr.info.opt) = optInfoNew(NULL((void*)0), foam, NULL((void*)0), false((int) 0)); |
| 312 | |
| 313 | foam->foamProg.infoBits |= IB_INLINEME(1 << 4); |
| 314 | |
| 315 | gen0ProgRestoreState(saved); |
| 316 | return clos; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | localstatic Foam |
| 321 | gen0GenerValueFun(FoamTag retType, TForm tf) |
| 322 | { |
| 323 | GenFoamState saved; |
| 324 | Foam foam, clos; |
| 325 | AInt fmt; |
| 326 | FoamTag type; |
| 327 | |
| 328 | type = gen0Type(tf, &fmt); |
Value stored to 'type' is never read | |
| 329 | clos = foamNewClos(foamNewEnv(-1), foamNewConst(gen0NumProgs))foamNew(FOAM_Clos,2, foamNew(FOAM_Env, 1, (AInt)(-1)), foamNew (FOAM_Const, 1, (AInt)(gen0NumProgs))); |
| 330 | foam = gen0ProgInitEmpty(valueFName()("generValue"), NULL((void*)0)); |
| 331 | |
| 332 | saved = gen0ProgSaveState(PT_Gener); |
| 333 | |
| 334 | gen0AddStmt(foamNewReturn(foamNewCast(FOAM_Word, yieldValVar))foamNew(FOAM_Return, 1, foamNew(FOAM_Cast, 2, FOAM_Word, gen0GetGenerVar (gen0GenVars, 2))), NULL((void*)0)); |
| 335 | |
| 336 | gen0UseStackedFormat(int0((int) 0)); |
| 337 | gen0ProgPushFormat(emptyFormatSlot4); |
| 338 | gen0ProgPushFormat(emptyFormatSlot4); |
| 339 | gen0ProgFiniEmpty(foam, FOAM_Word, emptyFormatSlot4); |
| 340 | |
| 341 | gen0AddLexLevels(foam, 2); |
| 342 | |
| 343 | foamOptInfo(foam)((foam)->hdr.info.opt) = optInfoNew(NULL((void*)0), foam, NULL((void*)0), false((int) 0)); |
| 344 | |
| 345 | gen0ProgRestoreState(saved); |
| 346 | return clos; |
| 347 | } |
| 348 | |
| 349 | /****************************************************************************** |
| 350 | * |
| 351 | * :: Lifting free generators, and computing bounds |
| 352 | * |
| 353 | *****************************************************************************/ |
| 354 | |
| 355 | DECLARE_LIST(GenBoundCalc)typedef struct GenBoundCalcListCons { GenBoundCalc first; struct GenBoundCalcListCons *rest; } *GenBoundCalcList; struct GenBoundCalc_listOpsStruct { GenBoundCalcList (*Cons) (GenBoundCalc, GenBoundCalcList); GenBoundCalcList (*Singleton) (GenBoundCalc); GenBoundCalcList (*List) (int n, ...); GenBoundCalcList (*Listv) (va_list argp ); GenBoundCalcList (*ListNull) (GenBoundCalc, ...); Bool (*Equal ) (GenBoundCalcList, GenBoundCalcList, Bool (*f) (GenBoundCalc , GenBoundCalc)); GenBoundCalc (*Find) (GenBoundCalcList, GenBoundCalc , Bool(*eq)(GenBoundCalc,GenBoundCalc) , int *); GenBoundCalc (*Match) (GenBoundCalcList, void *, Bool(*match)(GenBoundCalc , void *), int *); GenBoundCalcList (*MatchAll) (GenBoundCalcList , void *, Bool(*match)(GenBoundCalc, void *)); GenBoundCalcList (*FreeCons) (GenBoundCalcList); void (*Free) (GenBoundCalcList ); GenBoundCalcList (*FreeTo) (GenBoundCalcList, GenBoundCalcList ); void (*FreeDeeply) (GenBoundCalcList, void (*f)(GenBoundCalc )); GenBoundCalcList (*FreeDeeplyTo) (GenBoundCalcList, GenBoundCalcList , void (*f) (GenBoundCalc) ); GenBoundCalcList (*FreeIfSat) ( GenBoundCalcList, void (*f)(GenBoundCalc), Bool (*s)(GenBoundCalc )); GenBoundCalc (*Elt) (GenBoundCalcList, Length); GenBoundCalcList (*Drop) (GenBoundCalcList, Length); GenBoundCalcList (*LastCons ) (GenBoundCalcList); Length (*_Length) (GenBoundCalcList); Bool (*IsLength) (GenBoundCalcList, Length); Bool (*IsShorter) (GenBoundCalcList , Length); Bool (*IsLonger) (GenBoundCalcList, Length); GenBoundCalcList (*Copy) (GenBoundCalcList); GenBoundCalcList (*CopyTo) (GenBoundCalcList , GenBoundCalcList); GenBoundCalcList (*CopyDeeply) (GenBoundCalcList , GenBoundCalc (*)(GenBoundCalc)); GenBoundCalcList (*CopyDeeplyTo ) (GenBoundCalcList, GenBoundCalcList, GenBoundCalc (*)(GenBoundCalc )); GenBoundCalcList (*Map) (GenBoundCalc (*f)(GenBoundCalc), GenBoundCalcList); GenBoundCalcList (*NMap) (GenBoundCalc (* f)(GenBoundCalc), GenBoundCalcList); GenBoundCalcList (*Reverse ) (GenBoundCalcList); GenBoundCalcList (*NReverse) (GenBoundCalcList ); GenBoundCalcList (*Concat) (GenBoundCalcList, GenBoundCalcList ); GenBoundCalcList (*NConcat) (GenBoundCalcList, GenBoundCalcList ); Bool (*Memq) (GenBoundCalcList, GenBoundCalc); Bool (*Member ) (GenBoundCalcList, GenBoundCalc, Bool(*eq)(GenBoundCalc,GenBoundCalc ) ); Bool (*ContainsAllq) (GenBoundCalcList, GenBoundCalcList ); Bool (*ContainsAnyq) (GenBoundCalcList, GenBoundCalcList); Bool (*ContainsAll) (GenBoundCalcList, GenBoundCalcList, Bool (*eq)(GenBoundCalc, GenBoundCalc)); Bool (*ContainsAny) (GenBoundCalcList , GenBoundCalcList, Bool (*eq)(GenBoundCalc, GenBoundCalc)); int (*Posq) (GenBoundCalcList, GenBoundCalc); int (*Position) (GenBoundCalcList , GenBoundCalc, Bool(*eq)(GenBoundCalc,GenBoundCalc) ); GenBoundCalcList (*NRemove) (GenBoundCalcList, GenBoundCalc, Bool(*eq)(GenBoundCalc ,GenBoundCalc) ); void (*FillVector) (GenBoundCalc *, GenBoundCalcList ); int (*Print) (FILE *, GenBoundCalcList, int (*pr)(FILE *, GenBoundCalc ) ); int (*GPrint) (FILE *, GenBoundCalcList, int (*pr)(FILE * , GenBoundCalc), char *l,char *m,char *r); int (*Format) (OStream , CString, GenBoundCalcList); }; extern struct GenBoundCalc_listOpsStruct const *GenBoundCalc_listPointer; |
| 356 | typedef enum { GB_Min, GB_Mult, GB_Sum, GB_One, GB_None, GB_Ask } GenBoundTag; |
| 357 | |
| 358 | struct GenBoundCalc { |
| 359 | GenBoundTag tag; |
| 360 | AbSyn code; |
| 361 | GenBoundCalcList subs; |
| 362 | }; |
| 363 | |
| 364 | localstatic GenBoundCalc gen0MakeBoundCalc (AbSyn, Bool); |
| 365 | localstatic GenBoundCalc gen0NewBoundCalc (GenBoundTag, AbSyn, GenBoundCalcList); |
| 366 | localstatic GenBoundCalc gen0MakeYieldBound (AbSyn); |
| 367 | localstatic GenBoundCalc gen0MakeRepeatBound (AbSyn, Bool); |
| 368 | localstatic GenBoundCalc gen0MakeIterBound (AbSyn, Bool); |
| 369 | localstatic GenBoundCalc gen0MakeForBound (AbSyn, Bool); |
| 370 | localstatic GenBoundCalc gen0MakeSeqBound (AbSyn, Bool); |
| 371 | localstatic Bool gen0VerifyExprBoundSafe (AbSyn, Bool); |
| 372 | localstatic AbSynList gen0FindIterVars (AbSyn); |
| 373 | |
| 374 | #ifdef GenerBetterGuesses |
| 375 | localstatic Foam gen0ComputeBoundExpr (GenBoundCalc, int); |
| 376 | localstatic Foam gen0ComputeBoundGener (AbSyn, int); |
| 377 | localstatic Foam gen0ComputeBCall (FoamBValTag, FoamList); |
| 378 | localstatic FoamBValTag gen0CalcToBuiltin (GenBoundTag); |
| 379 | localstatic Foam gen0ComputeMin (FoamList); |
| 380 | #endif |
| 381 | |
| 382 | /* I/face to forIter from bound calc */ |
| 383 | |
| 384 | struct GenerGenInfo { |
| 385 | AbSynList geners; |
| 386 | FoamList foamVars; |
| 387 | FoamList nestChecks; |
| 388 | AbSynList ids; |
| 389 | }; |
| 390 | |
| 391 | /* Same order as GenCalcTags */ |
| 392 | FoamBValTag gen0CalcOps[] = { |
| 393 | FOAM_BVal_SIntMin, |
| 394 | FOAM_BVal_SIntTimes, |
| 395 | FOAM_BVal_SIntPlus, |
| 396 | 0, |
| 397 | 0, |
| 398 | 0, |
| 399 | }; |
| 400 | |
| 401 | CREATE_LIST(GenBoundCalc)struct GenBoundCalc_listOpsStruct const *GenBoundCalc_listPointer = (struct GenBoundCalc_listOpsStruct const *) &ptrlistOps; |
| 402 | |
| 403 | localstatic GenBoundCalc |
| 404 | gen0NewBoundCalc(GenBoundTag tag, AbSyn absyn, GenBoundCalcList subs) |
| 405 | { |
| 406 | GenBoundCalc new; |
| 407 | new = (GenBoundCalc) stoAlloc(OB_Other0, sizeof(*new)); |
| 408 | new->tag = tag; |
| 409 | new->code = absyn; |
| 410 | new->subs = subs; |
| 411 | |
| 412 | return new; |
| 413 | } |
| 414 | |
| 415 | #ifdef GenerBetterGuesses |
| 416 | localstatic GenBoundCalc |
| 417 | gen0MakeBoundInit(AbSyn absyn) |
| 418 | { |
| 419 | GenBoundCalc calc; |
| 420 | |
| 421 | gen0GenInfo = (GenerGenInfo) stoAlloc(OB_Other0, sizeof(*gen0GenInfo)); |
| 422 | gen0GenInfo->ids = listNil(AbSyn)((AbSynList) 0); |
| 423 | gen0GenInfo->geners = listNil(AbSyn)((AbSynList) 0); |
| 424 | gen0GenInfo->nestChecks = listNil(Foam)((FoamList) 0); |
| 425 | gen0GenInfo->foamVars = listNil(Foam)((FoamList) 0); |
| 426 | |
| 427 | calc = gen0MakeBoundCalc(absyn, false((int) 0)); |
| 428 | |
| 429 | if (!calc) { |
| 430 | listFree(AbSyn)(AbSyn_listPointer->Free)(gen0GenInfo->ids); |
| 431 | listFree(AbSyn)(AbSyn_listPointer->Free)(gen0GenInfo->geners); |
| 432 | listFree(Foam)(Foam_listPointer->Free)(gen0GenInfo->nestChecks); |
| 433 | listFree(Foam)(Foam_listPointer->Free)(gen0GenInfo->foamVars); |
| 434 | gen0GenInfo->ids = listNil(AbSyn)((AbSynList) 0); |
| 435 | gen0GenInfo->geners = listNil(AbSyn)((AbSynList) 0); |
| 436 | gen0GenInfo->nestChecks = listNil(Foam)((FoamList) 0); |
| 437 | gen0GenInfo->foamVars = listNil(Foam)((FoamList) 0); |
| 438 | } |
| 439 | return calc; |
| 440 | } |
| 441 | |
| 442 | localstatic Foam |
| 443 | gen0ComputeBoundFunction(GenBoundCalc calc) |
| 444 | { |
| 445 | GenFoamState saved; |
| 446 | Foam clos, foam, ret; |
| 447 | int exitLabel, retLabel; |
| 448 | |
| 449 | clos = foamNewClos(foamNewEnv(-1), foamNewConst(gen0NumProgs))foamNew(FOAM_Clos,2, foamNew(FOAM_Env, 1, (AInt)(-1)), foamNew (FOAM_Const, 1, (AInt)(gen0NumProgs))); |
| 450 | foam = gen0ProgInitEmpty(boundFName()("generBound"), NULL((void*)0)); |
| 451 | saved = gen0ProgSaveState(PT_Std); |
| 452 | |
| 453 | exitLabel = gen0State->labelNo++; |
| 454 | retLabel = gen0State->labelNo++; |
| 455 | |
| 456 | ret = gen0TempLocal(FOAM_SInt)gen0TempLocal0(FOAM_SInt, 4); |
| 457 | gen0AddStmt(foamNewSet(ret, gen0ComputeBoundExpr(calc, exitLabel))foamNew(FOAM_Set, 2, ret, gen0ComputeBoundExpr(calc, exitLabel )), NULL((void*)0)); |
| 458 | gen0AddStmt(foamNewGoto(retLabel)foamNew(FOAM_Goto, 1, (AInt)(retLabel)), NULL((void*)0)); |
| 459 | gen0AddStmt(foamNewLabel(exitLabel)foamNew(FOAM_Label, 1, (AInt)(exitLabel)), NULL((void*)0)); |
| 460 | gen0AddStmt(foamNewSet(foamCopy(ret), foamNewSInt(-1))foamNew(FOAM_Set, 2, foamCopy(ret), foamNew(FOAM_SInt, 1, (AInt )(-1))), NULL((void*)0)); |
| 461 | gen0AddStmt(foamNewLabel(retLabel)foamNew(FOAM_Label, 1, (AInt)(retLabel)), NULL((void*)0)); |
| 462 | gen0AddStmt(foamNewReturn(foamCopy(ret))foamNew(FOAM_Return, 1, foamCopy(ret)), NULL((void*)0)); |
| 463 | |
| 464 | foamOptInfo(foam)((foam)->hdr.info.opt) = optInfoNew(NULL((void*)0), foam, NULL((void*)0), true1); |
| 465 | |
| 466 | foam->foamProg.infoBits = IB_SIDE(1 << 0) | IB_INLINEME(1 << 4); |
| 467 | |
| 468 | gen0ProgPushFormat(emptyFormatSlot4); |
| 469 | gen0ProgPushFormat(emptyFormatSlot4); |
| 470 | gen0ProgFiniEmpty(foam, FOAM_SInt, int0((int) 0)); |
| 471 | gen0AddLexLevels(foam, 2); |
| 472 | |
| 473 | gen0ProgRestoreState(saved); |
| 474 | return clos; |
| 475 | } |
| 476 | #endif |
| 477 | |
| 478 | Foam |
| 479 | gen0GenLiftedGener(AbSyn forIter, AbSyn gener) |
| 480 | { |
| 481 | #ifndef GenerBetterGuesses |
| 482 | return genImplicit(forIter, gener, FOAM_Clos); |
| 483 | #else |
| 484 | Foam check, vars, call; |
| 485 | int place, i; |
| 486 | |
| 487 | if (gen0GenInfo) |
| 488 | place = listPosq(AbSyn)(AbSyn_listPointer->Posq)(gen0GenInfo->geners, forIter); |
| 489 | else |
| 490 | place = -1; |
| 491 | |
| 492 | if (place < 0) { |
| 493 | Foam vals = gen0TempFrDDecl(gen0MakeGenerRetFormat(), true1); |
| 494 | Foam doneFun = gen0Temp(FOAM_Clos)gen0Temp0(FOAM_Clos, 4); |
| 495 | Foam stepFun = gen0Temp(FOAM_Clos)gen0Temp0(FOAM_Clos, 4); |
| 496 | Foam valueFun = gen0Temp(FOAM_Clos)gen0Temp0(FOAM_Clos, 4); |
| 497 | Foam boundFun = gen0Temp(FOAM_Clos)gen0Temp0(FOAM_Clos, 4); |
| 498 | |
| 499 | call = foamNewEmpty(FOAM_CCall, 2); |
| 500 | call->foamCCall.type = FOAM_NOp; |
| 501 | call->foamCCall.op = genImplicit(forIter, gener, FOAM_Clos); |
| 502 | call = foamNewMFmt(gen0MakeGenerRetFormat(), call)foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat(), call); |
| 503 | gen0AddStmt(foamNewDef(foamCopy(vals), call)foamNew(FOAM_Def, 2, foamCopy(vals), call), forIter); |
| 504 | gen0AddStmt(foamNewDef(doneFun, vals->foamValues.argv[0])foamNew(FOAM_Def, 2, doneFun, vals->foamValues.argv[0]), |
| 505 | forIter); |
| 506 | gen0AddStmt(foamNewDef(stepFun, vals->foamValues.argv[1])foamNew(FOAM_Def, 2, stepFun, vals->foamValues.argv[1]), |
| 507 | forIter); |
| 508 | gen0AddStmt(foamNewDef(valueFun, vals->foamValues.argv[2])foamNew(FOAM_Def, 2, valueFun, vals->foamValues.argv[2]), |
| 509 | forIter); |
| 510 | gen0AddStmt(foamNewDef(boundFun, vals->foamValues.argv[3])foamNew(FOAM_Def, 2, boundFun, vals->foamValues.argv[3]), |
| 511 | forIter); |
| 512 | return foamNew(FOAM_Values, 4, doneFun, stepFun, |
| 513 | valueFun, boundFun); |
| 514 | } |
| 515 | check = listElt(Foam)(Foam_listPointer->Elt)(gen0GenInfo->nestChecks, place); |
| 516 | vars = listElt(Foam)(Foam_listPointer->Elt)(gen0GenInfo->foamVars, place); |
| 517 | if (check) { |
| 518 | Foam vals = gen0TempFrDDecl(gen0MakeGenerRetFormat(), true1); |
| 519 | |
| 520 | call = foamNewEmpty(FOAM_CCall, 2); |
| 521 | call->foamCCall.type = FOAM_NOp; |
| 522 | call->foamCCall.op = genImplicit(forIter, |
| 523 | forIter->abFor.whole, |
| 524 | FOAM_Clos); |
| 525 | gen0AddStmt(foamNewDef(foamCopy(vals),foamNew(FOAM_Def, 2, foamCopy(vals), foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat (), call)) |
| 526 | foamNewMFmt(gen0MakeGenerRetFormat(),foamNew(FOAM_Def, 2, foamCopy(vals), foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat (), call)) |
| 527 | call))foamNew(FOAM_Def, 2, foamCopy(vals), foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat (), call)), forIter); |
| 528 | gen0AddStmt(foamNewDef(foamCopy(check), foamNewBool(true))foamNew(FOAM_Def, 2, foamCopy(check), foamNew(FOAM_Bool, 1, ( AInt)(1))), |
| 529 | forIter); |
| 530 | for (i=0; i < 4; i++) |
| 531 | gen0AddStmt(foamNewDef(foamCopy(varsfoamNew(FOAM_Def, 2, foamCopy(vars ->foamValues.argv[i]), foamCopy (vals ->foamValues.argv[i])) |
| 532 | ->foamValues.argv[i]),foamNew(FOAM_Def, 2, foamCopy(vars ->foamValues.argv[i]), foamCopy (vals ->foamValues.argv[i])) |
| 533 | foamCopy(valsfoamNew(FOAM_Def, 2, foamCopy(vars ->foamValues.argv[i]), foamCopy (vals ->foamValues.argv[i])) |
| 534 | ->foamValues.argv[i]))foamNew(FOAM_Def, 2, foamCopy(vars ->foamValues.argv[i]), foamCopy (vals ->foamValues.argv[i])), |
| 535 | forIter); |
| 536 | return foamCopy(vars); |
| 537 | } |
| 538 | return foamCopy(vars); |
| 539 | #endif |
| 540 | } |
| 541 | |
| 542 | /* Internal bound calculation routines */ |
| 543 | localstatic GenBoundCalc |
| 544 | gen0MakeBoundCalc(AbSyn absyn, Bool nestCheck) |
| 545 | { |
| 546 | switch (abTag(absyn)((absyn)->abHdr.tag)) { |
| 547 | case AB_Yield: |
| 548 | return gen0MakeYieldBound(absyn); |
| 549 | case AB_Sequence: |
| 550 | return gen0MakeSeqBound(absyn, nestCheck); |
| 551 | case AB_Repeat: |
| 552 | return gen0MakeRepeatBound(absyn, nestCheck); |
| 553 | /* Nasty problems with side-effects if we allow apply, set, etc. */ |
| 554 | default: |
| 555 | return NULL((void*)0); |
| 556 | } |
| 557 | } |
| 558 | |
| 559 | localstatic GenBoundCalc |
| 560 | gen0MakeYieldBound(AbSyn absyn) |
| 561 | { |
| 562 | if (gen0VerifyExprBoundSafe(absyn->abYield.value, false((int) 0))) |
| 563 | return gen0NewBoundCalc(GB_One, NULL((void*)0), NULL((void*)0)); |
| 564 | else |
| 565 | return NULL((void*)0); |
| 566 | } |
| 567 | |
| 568 | localstatic GenBoundCalc |
| 569 | gen0MakeRepeatBound(AbSyn absyn, Bool nestCheck) |
| 570 | { |
| 571 | GenBoundCalc inner, loop; |
| 572 | GenBoundCalcList lst; |
| 573 | |
| 574 | if (nestCheck) return NULL((void*)0); |
| 575 | /* calcs ids too.. */ |
| 576 | loop = gen0MakeIterBound(absyn, nestCheck); |
| 577 | if (!loop) |
| 578 | return NULL((void*)0); |
| 579 | inner = gen0MakeBoundCalc(absyn->abRepeat.body, true1); |
| 580 | if (!inner) |
| 581 | return NULL((void*)0); |
| 582 | lst = listCons(GenBoundCalc)(GenBoundCalc_listPointer->Cons)(loop, |
| 583 | listCons(GenBoundCalc)(GenBoundCalc_listPointer->Cons)(inner, listNil(GenBoundCalc)((GenBoundCalcList) 0))); |
| 584 | return gen0NewBoundCalc(GB_Mult, NULL((void*)0), lst); |
| 585 | |
| 586 | } |
| 587 | |
| 588 | localstatic GenBoundCalc |
| 589 | gen0MakeIterBound(AbSyn ab, Bool nestCheck) |
| 590 | { |
| 591 | GenBoundCalcList lst = listNil(GenBoundCalc)((GenBoundCalcList) 0); |
| 592 | GenBoundCalc new; |
| 593 | AbSyn iter; |
| 594 | int i; |
| 595 | String msg; |
| 596 | |
| 597 | if (abRepeatIterc(ab)(((ab)->abHdr.argc)-1) == 0) { |
| 598 | return NULL((void*)0); |
| 599 | } |
| 600 | |
| 601 | if (abRepeatIterc(ab)(((ab)->abHdr.argc)-1) == 1) { |
| 602 | iter = ab->abRepeat.iterv[0]; |
| 603 | switch (abTag(iter)((iter)->abHdr.tag)) { |
| 604 | case AB_While: |
| 605 | new = NULL((void*)0); |
| 606 | break; |
| 607 | case AB_For: |
| 608 | new = gen0MakeForBound(iter, nestCheck); |
| 609 | break; |
| 610 | default: |
| 611 | msg = "bad iterator passed to gen0MakeIterBound"; |
| 612 | comsgFatal(ab, ALDOR_F_Bug365, msg); |
| 613 | #if 0 |
| 614 | bug("not an iterate"); |
| 615 | new = NULL((void*)0); |
| 616 | #endif |
| 617 | NotReached(new = NULL){(void)bug("Not supposed to reach line %d in file: %s\n",617, "gf_gener.c");}; |
| 618 | } |
| 619 | return new; |
| 620 | } |
| 621 | for (i=0; i<abRepeatIterc(ab)(((ab)->abHdr.argc)-1); i++) { |
| 622 | iter = ab->abRepeat.iterv[i]; |
| 623 | switch(abTag(iter)((iter)->abHdr.tag)) { |
| 624 | case AB_For: |
| 625 | new = gen0MakeForBound(iter, nestCheck); |
| 626 | if (!new) { |
| 627 | listFree(GenBoundCalc)(GenBoundCalc_listPointer->Free)(lst); |
| 628 | return NULL((void*)0); |
| 629 | } |
| 630 | lst = listCons(GenBoundCalc)(GenBoundCalc_listPointer->Cons)(new, lst); |
| 631 | break; |
| 632 | case AB_While: |
| 633 | if (!gen0VerifyExprBoundSafe(iter->abWhile.test, false((int) 0))) |
| 634 | return NULL((void*)0); |
| 635 | break; |
| 636 | default: |
| 637 | msg = "bad iterator passed to gen0MakeIterBound"; |
| 638 | comsgFatal(ab, ALDOR_F_Bug365, msg); |
| 639 | #if 0 |
| 640 | bug("not an iterator"); |
| 641 | return NULL((void*)0); |
| 642 | #endif |
| 643 | } |
| 644 | } |
| 645 | return gen0NewBoundCalc(GB_Min, NULL((void*)0), lst); |
| 646 | } |
| 647 | |
| 648 | localstatic GenBoundCalc |
| 649 | gen0MakeForBound(AbSyn absyn, Bool nestCheck) |
| 650 | { |
| 651 | if (!gen0VerifyExprBoundSafe(absyn->abFor.lhs, true1) || |
| 652 | !gen0VerifyExprBoundSafe(absyn->abFor.test, false((int) 0))) |
| 653 | return NULL((void*)0); |
| 654 | |
| 655 | gen0GenInfo->ids = listNConcat(AbSyn)(AbSyn_listPointer->NConcat)(gen0FindIterVars(absyn->abFor.lhs), |
| 656 | gen0GenInfo->ids); |
| 657 | gen0GenInfo->geners = listCons(AbSyn)(AbSyn_listPointer->Cons)(absyn, gen0GenInfo->geners); |
| 658 | /* should check nestCheck if we want to un-nest gtor */ |
| 659 | gen0GenInfo->nestChecks = listCons(Foam)(Foam_listPointer->Cons)(gen0TempLex(FOAM_Bool)gen0TempLex0(FOAM_Bool, 4), |
| 660 | gen0GenInfo->nestChecks); |
| 661 | return gen0NewBoundCalc(GB_Ask, absyn, NULL((void*)0)); |
| 662 | } |
| 663 | |
| 664 | localstatic AbSynList |
| 665 | gen0FindIterVars(AbSyn ab) |
| 666 | { |
| 667 | AbSynList lst = listNil(AbSyn)((AbSynList) 0); |
| 668 | int i; |
| 669 | String msg; |
| 670 | |
| 671 | switch (abTag(ab)((ab)->abHdr.tag)) { |
| 672 | case AB_Id: |
| 673 | lst = listCons(AbSyn)(AbSyn_listPointer->Cons)(ab, listNil(AbSyn)((AbSynList) 0)); |
| 674 | break; |
| 675 | case AB_Declare: |
| 676 | lst = gen0FindIterVars(ab->abDeclare.id); |
| 677 | break; |
| 678 | case AB_Free: |
| 679 | case AB_Fluid: |
| 680 | lst = listNil(AbSyn)((AbSynList) 0); |
| 681 | for (i=0; i < abArgc(ab)((ab)->abHdr.argc); i++) |
| 682 | lst = listNConcat(AbSyn)(AbSyn_listPointer->NConcat)(gen0FindIterVars(abArgv(ab)((ab)->abGen.data.argv)[i]), lst); |
| 683 | break; |
| 684 | case AB_Comma: |
| 685 | lst = listNil(AbSyn)((AbSynList) 0); |
| 686 | for (i=0; i < abArgc(ab)((ab)->abHdr.argc); i++) |
| 687 | lst = listNConcat(AbSyn)(AbSyn_listPointer->NConcat)(gen0FindIterVars(abArgv(ab)((ab)->abGen.data.argv)[i]), lst); |
| 688 | break; |
| 689 | default: |
| 690 | msg = "bad iterator passed to gen0FindIterVars"; |
| 691 | comsgFatal(ab, ALDOR_F_Bug365, msg); |
| 692 | #if 0 |
| 693 | abPrint(dbOut, ab); |
| 694 | bug("unhandled iteration form"); |
| 695 | NotReached(lst = listNil(AbSyn)){(void)bug("Not supposed to reach line %d in file: %s\n",695, "gf_gener.c");}; |
| 696 | break; |
| 697 | #endif |
| 698 | } |
| 699 | return lst; |
| 700 | } |
| 701 | |
| 702 | localstatic GenBoundCalc |
| 703 | gen0MakeSeqBound(AbSyn absyn, Bool nestCheck) |
| 704 | { |
| 705 | GenBoundCalcList lst = listNil(GenBoundCalc)((GenBoundCalcList) 0); |
| 706 | GenBoundCalc val; |
| 707 | int i; |
| 708 | |
| 709 | if (abArgc(absyn)((absyn)->abHdr.argc) == 0) |
| 710 | return gen0NewBoundCalc(GB_None, NULL((void*)0), NULL((void*)0)); |
| 711 | for (i=0; i < abArgc(absyn)((absyn)->abHdr.argc); i++) { |
| 712 | val = gen0MakeBoundCalc(absyn->abSequence.argv[i], nestCheck); |
| 713 | if (!val) { |
| 714 | listFree(GenBoundCalc)(GenBoundCalc_listPointer->Free)(lst); |
| 715 | return NULL((void*)0); |
| 716 | } |
| 717 | |
| 718 | lst = listCons(GenBoundCalc)(GenBoundCalc_listPointer->Cons)(val, lst); |
| 719 | } |
| 720 | |
| 721 | if (!lst) { |
| 722 | return NULL((void*)0); |
| 723 | } |
| 724 | return gen0NewBoundCalc(GB_Sum, NULL((void*)0), lst); |
| 725 | } |
| 726 | |
| 727 | localstatic Bool |
| 728 | gen0VerifyExprBoundSafe(AbSyn ab, Bool iterIds) |
| 729 | { |
| 730 | int i; |
| 731 | switch(abTag(ab)((ab)->abHdr.tag)) { |
| 732 | case AB_Id: |
| 733 | if (iterIds && listMember(AbSyn)(AbSyn_listPointer->Member)(gen0GenInfo->ids, ab, abEqual)) { |
| 734 | return false((int) 0); |
| 735 | } |
| 736 | return true1; |
| 737 | case AB_Yield: |
| 738 | case AB_Goto: |
| 739 | case AB_Sequence: |
| 740 | return false((int) 0); |
| 741 | case AB_LitInteger: |
| 742 | case AB_LitFloat: |
| 743 | case AB_LitString: |
| 744 | return true1; |
| 745 | default: |
| 746 | for (i=0; i<abArgc(ab)((ab)->abHdr.argc); i++) |
| 747 | if (!gen0VerifyExprBoundSafe(abArgv(ab)((ab)->abGen.data.argv)[i], iterIds)) { |
| 748 | return false((int) 0); |
| 749 | } |
| 750 | return true1; |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | #ifdef GenerBetterGuesses |
| 755 | |
| 756 | /* Added at generator base */ |
| 757 | localstatic void |
| 758 | gen0ComputeGeners() |
| 759 | { |
| 760 | AbSynList idlst, glst; |
| 761 | FoamList foamVars, nestlst; |
| 762 | Foam tmpVar, genVals; |
| 763 | |
| 764 | Foam vals = gen0TempFrDDecl(gen0MakeGenerRetFormat(), true1); |
| 765 | int i; |
| 766 | |
| 767 | idlst = listNReverse(AbSyn)(AbSyn_listPointer->NReverse)(gen0GenInfo->ids); |
| 768 | glst = listNReverse(AbSyn)(AbSyn_listPointer->NReverse)(gen0GenInfo->geners); |
| 769 | nestlst = listNReverse(Foam)(Foam_listPointer->NReverse)(gen0GenInfo->nestChecks); |
| 770 | gen0GenInfo->geners = glst; |
| 771 | gen0GenInfo->ids = idlst; |
| 772 | gen0GenInfo->nestChecks = nestlst; |
| 773 | |
| 774 | foamVars = listNil(Foam)((FoamList) 0); |
| 775 | while (glst) { |
| 776 | Foam doneFun = gen0TempLex(FOAM_Clos)gen0TempLex0(FOAM_Clos, 4); |
| 777 | Foam stepFun = gen0TempLex(FOAM_Clos)gen0TempLex0(FOAM_Clos, 4); |
| 778 | Foam valueFun = gen0TempLex(FOAM_Clos)gen0TempLex0(FOAM_Clos, 4); |
| 779 | Foam boundFun = gen0TempLex(FOAM_Clos)gen0TempLex0(FOAM_Clos, 4); |
| 780 | FoamTag type; |
| 781 | AInt fmt; |
| 782 | |
| 783 | type = gen0Type(gen0AbType(car(idlst)((idlst)->first)), &fmt); |
| 784 | tmpVar = gen0TempLocal0(type, fmt); |
| 785 | foamVars = listCons(Foam)(Foam_listPointer->Cons)(foamNew(FOAM_Values, 4, doneFun, stepFun, |
| 786 | valueFun, boundFun), foamVars); |
| 787 | if (car(nestlst)((nestlst)->first)) |
| 788 | gen0AddStmt(foamNewSet(car(nestlst), foamNewBool(false))foamNew(FOAM_Set, 2, ((nestlst)->first), foamNew(FOAM_Bool , 1, (AInt)(((int) 0)))), NULL((void*)0)); |
| 789 | else { |
| 790 | genVals = genImplicit(car(glst)((glst)->first), car(glst)((glst)->first)->abFor.whole, FOAM_Clos); |
| 791 | gen0AddStmt(foamNewSet(tmpVar, genVals)foamNew(FOAM_Set, 2, tmpVar, genVals), NULL((void*)0)); |
| 792 | genVals = foamNewMFmt(gen0MakeGenerRetFormat(),foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat(), foamNew(FOAM_CCall , 2, FOAM_NOp, foamCopy(tmpVar))) |
| 793 | foamNew(FOAM_CCall, 2,foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat(), foamNew(FOAM_CCall , 2, FOAM_NOp, foamCopy(tmpVar))) |
| 794 | FOAM_NOp, foamCopy(tmpVar)))foamNew(FOAM_MFmt, 2, gen0MakeGenerRetFormat(), foamNew(FOAM_CCall , 2, FOAM_NOp, foamCopy(tmpVar))); |
| 795 | gen0AddStmt(foamNewSet(foamCopy(vals), genVals)foamNew(FOAM_Set, 2, foamCopy(vals), genVals), NULL((void*)0)); |
| 796 | for (i=0; i<foamArgc(vals)((vals)->hdr.argc); i++) |
| 797 | gen0AddStmt(foamNewSet(foamCopy(car(foamVars)->foamValues.argv[i]),foamNew(FOAM_Set, 2, foamCopy(((foamVars)->first)->foamValues .argv[i]), foamCopy(vals->foamValues.argv[i])) |
| 798 | foamCopy(vals->foamValues.argv[i]))foamNew(FOAM_Set, 2, foamCopy(((foamVars)->first)->foamValues .argv[i]), foamCopy(vals->foamValues.argv[i])), NULL((void*)0)); |
| 799 | } |
| 800 | idlst = cdr(idlst)((idlst)->rest); |
| 801 | glst = cdr(glst)((glst)->rest); |
| 802 | nestlst = cdr(nestlst)((nestlst)->rest); |
| 803 | } |
| 804 | foamFree(vals); |
| 805 | gen0GenInfo->foamVars = listNReverse(Foam)(Foam_listPointer->NReverse)(foamVars); |
| 806 | } |
| 807 | |
| 808 | localstatic Foam |
| 809 | gen0ComputeBoundExpr(GenBoundCalc calc, int exitLabel) |
| 810 | { |
| 811 | FoamList lst; |
| 812 | Foam val; |
| 813 | GenBoundCalcList clst; |
| 814 | |
| 815 | switch(calc->tag) { |
| 816 | case GB_One: |
| 817 | val = foamNewSInt(1)foamNew(FOAM_SInt, 1, (AInt)(1)); |
| 818 | break; |
| 819 | case GB_None: |
| 820 | val = foamNewSInt(int0)foamNew(FOAM_SInt, 1, (AInt)(((int) 0))); |
| 821 | break; |
| 822 | case GB_Ask: /* Look in list for foam */ |
| 823 | val = gen0ComputeBoundGener(calc->code, exitLabel); |
| 824 | break; |
| 825 | default: |
| 826 | lst = listNil(Foam)((FoamList) 0); |
| 827 | clst = calc->subs; |
| 828 | while (clst) { |
| 829 | lst = listCons(Foam)(Foam_listPointer->Cons) |
| 830 | (gen0ComputeBoundExpr(car(clst)((clst)->first), exitLabel), |
| 831 | lst); |
| 832 | clst = cdr(clst)((clst)->rest); |
| 833 | } |
| 834 | if (calc->tag == GB_Min) |
| 835 | val = gen0ComputeMin(lst); |
| 836 | else |
| 837 | val = gen0ComputeBCall(gen0CalcToBuiltin(calc->tag), lst); |
| 838 | } |
| 839 | return val; |
| 840 | } |
| 841 | |
| 842 | localstatic Foam |
| 843 | gen0ComputeBoundGener(AbSyn code, int exitLabel) |
| 844 | { |
| 845 | Foam tmp = gen0TempLocal(FOAM_SInt)gen0TempLocal0(FOAM_SInt, 4); |
| 846 | Foam vals, nestCheck, call; |
| 847 | int place; |
| 848 | |
| 849 | place = listPosq(AbSyn)(AbSyn_listPointer->Posq)(gen0GenInfo->geners, code); |
| 850 | vals = listElt(Foam)(Foam_listPointer->Elt)(gen0GenInfo->foamVars, place); |
| 851 | nestCheck = listElt(Foam)(Foam_listPointer->Elt)(gen0GenInfo->nestChecks, place); |
| 852 | |
| 853 | if (nestCheck) { |
| 854 | gen0AddStmt(foamNewIf(foamNotThis(foamCopy(nestCheck)),foamNew(FOAM_If, 2, foamNotThis(foamCopy(nestCheck)), exitLabel ) |
| 855 | exitLabel)foamNew(FOAM_If, 2, foamNotThis(foamCopy(nestCheck)), exitLabel ), NULL((void*)0)); |
| 856 | } |
| 857 | call = foamNewEmpty(FOAM_CCall, 2); |
| 858 | call->foamCCall.type = FOAM_SInt; |
| 859 | call->foamCCall.op = foamCopy(vals->foamValues.argv[boundPlace3]); |
| 860 | |
| 861 | gen0AddStmt(foamNewSet(tmp, call)foamNew(FOAM_Set, 2, tmp, call), NULL((void*)0)); |
| 862 | gen0AddStmt(foamNewIf(foamNew(FOAM_BCall, 3, (AInt)FOAM_BVal_SIntLT,foamNew(FOAM_If, 2, foamNew(FOAM_BCall, 3, (AInt)FOAM_BVal_SIntLT , foamCopy(tmp), foamNew(FOAM_SInt, 1, (AInt)(((int) 0)))), exitLabel ) |
| 863 | foamCopy(tmp), foamNewSInt(int0)),foamNew(FOAM_If, 2, foamNew(FOAM_BCall, 3, (AInt)FOAM_BVal_SIntLT , foamCopy(tmp), foamNew(FOAM_SInt, 1, (AInt)(((int) 0)))), exitLabel ) |
| 864 | exitLabel)foamNew(FOAM_If, 2, foamNew(FOAM_BCall, 3, (AInt)FOAM_BVal_SIntLT , foamCopy(tmp), foamNew(FOAM_SInt, 1, (AInt)(((int) 0)))), exitLabel ), NULL((void*)0)); |
| 865 | gen0UseStackedFormat(int0((int) 0)); |
| 866 | return foamCopy(tmp); |
| 867 | } |
| 868 | |
| 869 | localstatic Foam |
| 870 | gen0ComputeMin(FoamList lst) |
| 871 | { |
| 872 | Foam acc = gen0TempLocal(FOAM_SInt)gen0TempLocal0(FOAM_SInt, 4); |
| 873 | |
| 874 | gen0AddStmt(foamNewSet(acc, car(lst))foamNew(FOAM_Set, 2, acc, ((lst)->first)), NULL((void*)0)); |
| 875 | lst = cdr(lst)((lst)->rest); |
| 876 | |
| 877 | while (lst) { |
| 878 | int label = gen0State->labelNo++; |
| 879 | gen0AddStmt(foamNewIf(foamNew(FOAM_BCall, 3, FOAM_BVal_SIntLT,foamNew(FOAM_If, 2, foamNew(FOAM_BCall, 3, FOAM_BVal_SIntLT, foamCopy (acc), ((lst)->first)), label) |
| 880 | foamCopy(acc), car(lst)), label)foamNew(FOAM_If, 2, foamNew(FOAM_BCall, 3, FOAM_BVal_SIntLT, foamCopy (acc), ((lst)->first)), label), |
| 881 | NULL((void*)0)); |
| 882 | gen0AddStmt(foamNewSet(foamCopy(acc), foamCopy(car(lst)))foamNew(FOAM_Set, 2, foamCopy(acc), foamCopy(((lst)->first ))), NULL((void*)0)); |
| 883 | gen0AddStmt(foamNewLabel(label)foamNew(FOAM_Label, 1, (AInt)(label)), NULL((void*)0)); |
| 884 | lst = cdr(lst)((lst)->rest); |
| 885 | } |
| 886 | return foamCopy(acc); |
| 887 | } |
| 888 | |
| 889 | localstatic Foam |
| 890 | gen0ComputeBCall(FoamBValTag fn, FoamList lst) |
| 891 | { |
| 892 | Foam acc; |
| 893 | if (cdr(lst)((lst)->rest)==0) return car(lst)((lst)->first); |
| 894 | acc = foamNew(FOAM_BCall, 3, fn, car(lst)((lst)->first), gen0ComputeBCall(fn, cdr(lst)((lst)->rest))); |
| 895 | return acc; |
| 896 | } |
| 897 | |
| 898 | localstatic FoamBValTag |
| 899 | gen0CalcToBuiltin(GenBoundTag tag) |
| 900 | { |
| 901 | assert(gen0CalcOps[tag])do { if (!(gen0CalcOps[tag])) _do_assert(("gen0CalcOps[tag]") ,"gf_gener.c",901); } while (0); |
| 902 | return gen0CalcOps[tag]; |
| 903 | } |
| 904 | |
| 905 | #endif |