# /* vim: set filetype=awk : */ -*- awk -*- ##---- [nudge.awk] ------------------------------------------ # needs normal.awk function gaussian(m,std,nudgep,old,nudge, delta,up,down,got,retries) { if (nudgep) { delta = normal(1,nudge); up = old + (std * delta); down = old - (std * delta); retries = 128; while(retries-- ) { got=normal(m,std); if (got >= down && got <= up) return got; } return old; } else { return normal(m,std) } } function ratio(min,max,nudgep,old,nudge, delta) { if (min==max) return min; if (nudgep) { delta=(max-min)*nudge/2; min=most(min,old-delta); max=least(max,old+delta); }; return between(min,max); } function ratioInt(min,max,nudgep,old,nudge, out,delta,aLittle) { if(min==max) return min; if (nudgep) { delta=(max-min)*nudge/2; min=most(min,old-delta); max=least(max,old+delta); } else { aLittle = 0.499999; min=min - aLittle; max=max + aLittle; }; return round(between(min,max)); } function ordinal(range,nudgep,old,nudge, i,j,dim) { dim=range[_n]; if (nudgep) { i=indexOf(old,range); j=ratioInt(1,dim,1,i,nudge); } else { j=ratioInt(1,dim); }; return range[j]; } function nominal(range,nudgep,old,nudge) { if (nudgep && nudge==0) { return old} else { return ordinal(range,nudgep,old,nudge)} } function indexOf(x,range,i) { for(i in range) { if (i < 0 ) continue; if (range[i]==x) return i; }; bad(x " not in range \n"); } function framep(x,w) { return ("frame",x) in w } function slottypes(types) { string2bool(types,"of,int,normal,real,=") } function compute(what,y,z, p,o,n) { if (what=="int") return ratioInt(y,z, p,o,n); if (what=="normal") return gaussian(y,z, p,o,n); if (what=="real") return ratio( y,z, p,o,n); if (what=="of") return ordinal( y, p,o,n); } function badSlot(n,e,txt) { bad("W> skipping line " n": " txt " (code "e")") } function readSlots(f,w,aka, isa,types, n,mins,i,oldFS,\ oldRS, oldIgnore,keyword,parent,here,x) { slottypes(types); string2pairs(mins,"of,4,with,3,=,3,just,4,is,4") oldFS = FS; oldRS = RS; oldIgnore = IGNORECASE; FS = " "; RS = "\n"; IGNORECASE = 1; here = "system" w["frame", here] = 1; while((getline < f) > 0) { n++; sub(/[#%].*/,"",$0); if ($0 ~ /^[ \t]*$/) continue; if (NF < 3) { badSlot(n,1,"not enough fields"); continue}; for(i=1;i<=NF;i++) $i=trim($i); keyword = $2; if (! (keyword in mins)) { badSlot(n,2,"unknown keyword '"keyword"'"); continue} if (NF < mins[keyword]) { badSlot(n,3,"need at least "mins[keyword]" fields");continue} if (keyword == "with") { parent=$1; here =$3; if (!w["frame",parent]) { badSlot(n,4,"'"parent"' unknown"); continue}; if ( w["frame",here] ) { badSlot(n,5,"'"here"' multiple definitions"); continue}; w["frame",here] = 1; w[parent,"child", ++w[parent,"child",0]]= here; w[here, "parent"] = parent; continue; } x = $1; if (keyword == "is") { if (! ($3 in types)) { badSlot(n,6,"'"$3"' unknown type"); continue} w["slot",$1]=1 w[here,x,"x" ]= $3; if ($3 == "of" ) { w[here,x,"y"]=0 for(i=4;i<=NF;i++) w[here,x, ++w[here,x,"y"]] = v2i($i,aka) } else { w[here,x,"y"]= v2i($4,aka); w[here,x,"z"]=v2i($5,aka) } } if (! (("slot",x) in w)) { badSlot(n,7,"'"x"' unknown"); continue} if (keyword == "=") w[here,x,"="]= v2i($3,aka); if (keyword == "just") { isa = slotIsa(here,x,w); if ( w[isa,x,"x"]== "of") { w[here,x,"y"]=0 for(i=3;i<=NF;i++) w[here,x, ++w[here,x,"y"]]=v2i($i,aka) } else { w[here,x,"y"]= v2i($3,aka); w[here,x,"z"]= v2i($4,aka) } } } if (! n) bad("'"f"' not found"); close(f); FS=oldFS; RS=oldRS; IGNORECASE = oldIgnore; } function v2i(x,aka) { return (x in aka) ? aka[x] : x } function slotIsa(fr,sl, wme) { if ( ! (("frame",fr) in wme) ) { return bad("'" fr "' unknown frame") }; if ( ! (("slot", sl) in wme) ) { return bad("'" sl "' unknown slot" ) }; if ( (fr,sl,"x") in wme ) { return fr } if ( fr=="system" ) { return bad("'" sl "' not found in slot tree") } else { return slotIsa(wme[fr,"parent"],sl,wme) } } function slot(fr,sl,wme) { if ( ! (("frame",fr) in wme) ) { return bad("'" fr "' unknown frame") }; if ( ! (("slot", sl) in wme) ) { return bad("'" sl "' unknown slot") }; if ( (fr,sl,"=") in wme) { return wme[fr, sl ,"="] } if ( (fr,sl,"y") in wme) { return slot1(fr,sl,wme); } if ( fr=="system" ) { return bad("'" sl "' not found in slot tree") } else { return slot(wme[fr,"parent"],sl,wme) } } function slot1(fr,sl,wme) { if (wme["system",sl,"x"]== "of") { return slotItem(fr,sl,wme); } else { return compute(wme["system",sl,"x"],wme[fr,sl,"y"],wme[fr,sl,"z"]) } } function slotItem(fr,sl,wme, max,pos) { max = wme[fr,sl,"y"] pos = ratioInt(1,max); return wme[fr,sl,pos] }