/*
(Concurrent) Clean Compiler: Code Generator
Authors: Sjaak Smetsers & John van Groningen
At: University of Nijmegen, department of computing science
Version: 1.2
*/
#pragma segment codegen2
#pragma options (!macsbug_names)
#define FASTER_STRICT_IF /* also in statesgen.c */
#define DO_LAZY_SELECTORS_FROM_BOXED_STRICT_RECORDS
#define FREE_STRICT_LHS_TUPLE_ELEMENTS 1 /* also in codegen1.c */
#define SELECTORS_FIRST 1 /* also in codegen.c */
#include "system.h"
#include "syntaxtr.t"
#include "comsupport.h"
#include "settings.h"
#include "sizes.h"
#include "checker.h"
#include "codegen_types.h"
#include "codegen.h"
#include "codegen1.h"
#include "codegen2.h"
#include "sa.h"
#include "statesgen.h"
#include "transform.h"
#include "instructions.h"
#include "typechecker.h"
#include "optimisations.h"
#include "buildtree.h"
#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n)
#define for_li(v,i,l,n) for(v=(l),i=0;v!=NULL;v=v->n,++i)
#define for_ll(v1,v2,l1,l2,n1,n2) for(v1=(l1),v2=(l2);v1!=NULL;v1=v1->n1,v2=v2->n2)
#define for_la(v1,v2,l1,l2,n1) for(v1=(l1),v2=(l2);v1!=NULL;v1=v1->n1,++v2)
static void error_in_function (char *m)
{
ErrorInCompiler ("codegen2.c",m,"");
}
char *Co_Wtype = "incorrect type";
char *Co_Wspine = "non-terminating rule specified";
char else_symb[] = "else";
char then_symb[] = "then";
char notused_string[] = "notused";
SymbDef ApplyDef,IfDef;
unsigned NewLabelNr;
StateS StrictOnAState;
static StateS UnderEvalState,ProcIdState;
StateS OnAState;
Bool LazyTupleSelectors [MaxNodeArity-NrOfGlobalSelectors];
LabDef BasicDescriptors [NrOfObjects];
int ObjectSizes [NrOfObjects];
static void InitBasicDescriptor (ObjectKind kind,char *name,int size)
{
BasicDescriptors[kind].lab_mod = NULL;
BasicDescriptors[kind].lab_pref = no_pref;
BasicDescriptors[kind].lab_issymbol = False;
BasicDescriptors[kind].lab_name = name;
BasicDescriptors[kind].lab_post = 0;
ObjectSizes[kind] = size;
}
Bool EqualState (StateS st1,StateS st2)
{
if (IsSimpleState (st1) && IsSimpleState (st2))
return st1.state_kind==st2.state_kind;
switch (st1.state_type){
case RecordState:
return st2.state_type==RecordState;
case TupleState:
if (st2.state_type==TupleState && st1.state_arity==st2.state_arity){
int i;
for (i=0; i<st1.state_arity; i++)
if (!EqualState (st1.state_tuple_arguments[i],st2.state_tuple_arguments[i]))
return False;
return True;
} else
return False;
case ArrayState:
return st2.state_type==ArrayState;
default:
return False;
}
}
/* int InitAStackTop,InitBStackTop; */
void NewEmptyNode (int *asp_p,int nrargs)
{
GenCreate (nrargs);
*asp_p += SizeOfAStackElem;
}
void save_node_id_state (NodeId node_id,SavedNidStateS **saved_nid_state_l)
{
SavedNidStateP new_saved_state;
new_saved_state=CompAllocType (SavedNidStateS);
new_saved_state->save_state=node_id->nid_state;
new_saved_state->save_node_id=node_id;
new_saved_state->save_next=*saved_nid_state_l;
*saved_nid_state_l=new_saved_state;
}
void restore_saved_node_id_states (SavedNidStateP saved_node_id_states)
{
while (saved_node_id_states){
saved_node_id_states->save_node_id->nid_state_=saved_node_id_states->save_state;
saved_node_id_states=saved_node_id_states->save_next;
}
}
static Bool CopyArgument (StateS demstate,StateS offstate,int aindex,int bindex,int *asp_p,int *bsp_p,int offasize,int offbsize,Bool newnode);
static void GenProcIdCalculation (Node node,Annotation annot,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (annot==ParallelAtAnnot){
Node procidnode;
procidnode=get_p_at_node (node);
if (procidnode->node_kind!=NodeIdNode)
Build (procidnode,asp_p,bsp_p,code_gen_node_ids_p);
else {
int asize,bsize;
NodeId nid;
nid=procidnode->node_node_id;
DetermineSizeOfState (nid->nid_state,&asize,&bsize);
CopyArgument (ProcIdState,nid->nid_state,nid->nid_a_index,nid->nid_b_index,asp_p,bsp_p,asize,bsize,False);
}
} else {
GenNewP();
++*bsp_p;
}
}
static void GenRedIdCalculation (Node redidnode,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (redidnode){
if (redidnode->node_kind!=NodeIdNode)
Build (redidnode,asp_p,bsp_p,code_gen_node_ids_p);
else {
int asize,bsize;
NodeId nid;
nid=redidnode->node_node_id;
DetermineSizeOfState (nid->nid_state,&asize, &bsize);
CopyArgument (ProcIdState,nid->nid_state,nid->nid_a_index,nid->nid_b_index,asp_p,bsp_p,asize, bsize, False);
}
} else
GenPushReducerId (-1);
}
static char *GetReducerCode (Annotation annot)
{
switch (annot)
{ case ParallelAnnot:
case ParallelAtAnnot:
return ext_hnf_reducer_code;
case ParallelNFAnnot:
return ext_nf_reducer_code;
default:
return "";
}
}
void UnpackRecord (int aindex,int *asp_p,int *bsp,Bool removeroot,int arity,States argstates)
{
int asize,bsize;
DetermineSizeOfStates (arity, argstates, & asize, & bsize);
if (removeroot)
GenReplRArgs (asize, bsize);
else
GenPushRArgs (*asp_p - aindex, asize , bsize);
*asp_p += asize;
*bsp += bsize;
}
static void UnpackArrayOnTopOfStack (void)
{
GenPushArray (0);
#if UPDATE_POP
GenUpdatePopA (0,1);
#else
GenUpdateA (0,1);
GenPopA (1);
#endif
}
void UnpackArray (int aindex, int *asp_p, Bool removeroot)
{
if (removeroot){
GenPushArray (0);
#if UPDATE_POP
GenUpdatePopA (0,1);
#else
GenUpdateA (0,1);
GenPopA (1);
#endif
} else
GenPushArray (*asp_p - aindex);
*asp_p += SizeOfAStackElem;
}
Coercions CoerceStateKind (StateKind dem_state_kind, StateKind off_state_kind)
{
if (dem_state_kind==Undefined)
error_in_function ("CoerceStateKind");
switch (off_state_kind){
case OnB:
if (dem_state_kind == OnB)
return BToB;
else
return BToA;
case OnA:
case SemiStrict:
case LazyRedirection:
if (dem_state_kind == OnA)
return AToA;
else
return Reduce;
case StrictOnA:
if (dem_state_kind == OnB)
return AToB;
else
return AToA;
case StrictRedirection:
if (dem_state_kind == OnB)
return AToB;
else if (dem_state_kind == StrictRedirection)
return AToA;
else
return AToRoot;
case Parallel:
if (dem_state_kind == OnA)
return AToA;
else
StaticMessage (False, "","parallel annotation in strict context ignored");
return Reduce;
case UnderEval:
if (dem_state_kind == OnA)
return MayBecomeCyclicSpine;
else
return CyclicSpine;
default:
error_in_function ("CoerceStateKind");
return AToA;
}
}
Bool TypeErrorFound, CycleErrorFound;
void GenReduceError (void)
{
GenDAStackLayout (0);
GenJsr (&cycle_lab);
GenOAStackLayout (0);
CycleErrorFound = True;
}
Coercions CoerceSimpleStateArgument (StateS demstate,StateKind offkind,int aindex,int *asp_p,Bool leaveontop, Bool *ontop)
{
Coercions c;
/* Examine the argument states to see whether it has to be reduced */
if (IsSimpleState (demstate))
c = CoerceStateKind (demstate.state_kind, offkind);
else
c = CoerceStateKind (StrictOnA, offkind);
switch (c){
case Reduce:
if (leaveontop){
GenPushA (*asp_p - aindex);
GenJsrEval (0);
*asp_p += SizeOfAStackElem;
*ontop = True;
} else {
GenJsrEval (*asp_p - aindex);
*ontop = False;
}
break;
case MayBecomeCyclicSpine:
GenCreate (-1);
*asp_p += SizeOfAStackElem;
*ontop = True;
break;
case CyclicSpine:
GenReduceError ();
StaticMessage (False,CurrentAltLabel.lab_symbol->sdef_ident->ident_name,Co_Wspine);
*ontop = False;
break;
default:
*ontop = False;
break;
}
return c;
}
static StateKind AdjustStateKind (StateKind statekind, Coercions c)
{
switch (c){
case Reduce:
return StrictOnA;
case MayBecomeCyclicSpine:
return OnA;
default:
return statekind;
}
}
static void CoerceArgumentsUsingStackFrames (int arity,States demstates,States offstates,int aindex,int bindex,
int *asp_p, int *bsp, int *anext, int *bnext, int asize, int bsize);
void CoerceArgumentUsingStackFrames (StateS demstate, StateS offstate,int aindex,int bindex,int *asp_p,int *bsp,
int *anext,int *bnext,int asize,int bsize)
{
if (IsSimpleState (demstate) && demstate.state_kind==Undefined)
return;
if (IsSimpleState (offstate)){
Coercions c;
Bool ontop;
StateKind offkind;
ontop = False;
offkind = offstate.state_kind;
c = CoerceSimpleStateArgument (demstate, offkind, aindex, asp_p, False, &ontop);
offkind = AdjustStateKind (offkind, c);
Assume (! ontop,"codegen","CoerceArgumentUsingStackFrames");
if (IsSimpleState (demstate)){
switch (CoerceStateKind (demstate.state_kind, offkind)){
case AToA:
case AToRoot:
PutInAFrames (aindex, anext);
return;
case AToB:
PushBasicFromAOnB (demstate.state_object, *asp_p - aindex);
*bsp += ObjectSizes [demstate.state_object];
PutInBFrames (*bsp, bnext, ObjectSizes [demstate.state_object]);
return;
case BToA:
++*asp_p;
BuildBasicFromB (offstate.state_object,*bsp - bindex);
PutInAFrames (*asp_p, anext);
return;
case BToB:
PutInBFrames (bindex, bnext, ObjectSizes [demstate.state_object]);
return;
default:
;
}
} else {
switch (demstate.state_type){
case TupleState:
/*
A tuple is demanded whereas a node is offered.
Each argument is converted to its demanded state. Note that
the offered state of each argument after pushing it on
the stack is 'OnAState'.
*/
{
int i,arity,index;
States argstates;
arity = demstate.state_arity;
argstates = demstate.state_tuple_arguments;
GenPushArgs (*asp_p - aindex, arity, arity);
*asp_p += arity;
index = *asp_p;
for (i=arity-1; i>=0; i--)
CoerceArgumentUsingStackFrames (argstates [i], OnAState,index-i, 0, asp_p, bsp, anext, bnext, 1, 0);
break;
}
case RecordState:
{
int asize,bsize,arity;
States argstates;
arity = demstate.state_arity;
argstates = demstate.state_record_arguments;
DetermineSizeOfStates (arity, argstates, &asize, &bsize);
GenPushRArgs (*asp_p - aindex, asize , bsize);
*asp_p += asize;
*bsp += bsize;
CoerceArgumentsUsingStackFrames (arity, argstates, argstates,*asp_p,*bsp, asp_p, bsp, anext, bnext, asize, bsize);
break;
}
case ArrayState:
GenPushArray (*asp_p-aindex);
*asp_p += 1;
PutInAFrames (*asp_p, anext);
break;
}
}
} else if (IsSimpleState (demstate)){
switch (offstate.state_type){
case TupleState:
BuildTuple (aindex, bindex, *asp_p, *bsp,offstate.state_arity, offstate.state_tuple_arguments,
asize,bsize,*asp_p,NormalFill,True);
*asp_p += SizeOfAStackElem;
break;
case RecordState:
BuildRecord (offstate.state_record_symbol,aindex, bindex, *asp_p, *bsp,
asize,bsize,*asp_p,NormalFill,True);
*asp_p += SizeOfAStackElem;
break;
case ArrayState:
GenBuildArray (*asp_p-aindex);
++*asp_p;
break;
}
PutInAFrames (*asp_p, anext);
} else {
switch (offstate.state_type){
case TupleState:
CoerceArgumentsUsingStackFrames
(demstate.state_arity, demstate.state_tuple_arguments,
offstate.state_tuple_arguments, aindex, bindex, asp_p, bsp, anext, bnext,
asize, bsize);
break;
case RecordState:
CoerceArgumentsUsingStackFrames
(demstate.state_arity,demstate.state_record_arguments,
offstate.state_record_arguments, aindex, bindex, asp_p, bsp, anext, bnext,
asize, bsize);
break;
case ArrayState:
PutInAFrames (aindex, anext);
break;
}
}
}
static void CoerceArgumentsUsingStackFrames (int arity, StateS demstates[], StateS offstates[],int aindex, int bindex,
int *asp_p, int *bsp, int *anext, int *bnext,int asize, int bsize)
{
int i;
aindex -= asize;
bindex -= bsize;
for (i=arity-1; i>=0; i--){
int asize,bsize;
DetermineSizeOfState (offstates[i],&asize, &bsize);
aindex += asize;
bindex += bsize;
CoerceArgumentUsingStackFrames (demstates [i],offstates [i],aindex,bindex,asp_p,bsp,anext,bnext,asize,bsize);
}
}
void AdjustTuple (int localasp,int localbsp,int *asp_p,int *bsp_p,int arity,StateS demstates[],StateS offstates[],int asize,int bsize)
{
int a_ind,b_ind,dummy,oldamax,oldbmax,newamax,newbmax;
a_ind=0;
b_ind=0;
dummy = 0,
newamax = localasp + 1 + arity;
newbmax = localbsp + 1;
AddStateSizesAndMaxFrameSizes (arity, demstates, &newamax, &dummy, &newbmax);
InitStackConversions (newamax, newbmax, &oldamax, &oldbmax);
CoerceArgumentsUsingStackFrames (arity, demstates, offstates, localasp, localbsp,
&localasp, &localbsp, &a_ind, &b_ind, asize, bsize);
GenAStackConversions (localasp,a_ind);
GenBStackConversions (localbsp,b_ind);
ExitStackConversions (oldamax, oldbmax);
*asp_p += a_ind-asize;
*bsp_p += b_ind-bsize;
}
void UnpackTuple (int aindex,int *asp_p,int *bsp_p,Bool removeroot,int arity,StateS argstates[])
{
int aselmts,oldaframesize,locasp,asize,maxasize;
aselmts = 0;
locasp = arity;
asize = 0;
maxasize = arity;
if (removeroot)
GenReplArgs (arity, arity);
else
GenPushArgs (*asp_p- aindex, arity, arity);
AddStateSizesAndMaxFrameSizes (arity, argstates, &maxasize, &asize,bsp_p);
InitAStackConversions (maxasize+1, &oldaframesize);
EvaluateAndMoveArguments (arity,argstates,&locasp,&aselmts);
GenAStackConversions (locasp,aselmts);
FreeAFrameSpace (oldaframesize);
*asp_p += aselmts;
}
static void MoveArgumentsFromBToA (int arity,States argstates,int aindex,int bindex,int asp_p,int bsp,int asize,int bsize)
{
int i;
aindex -= asize;
bindex -= bsize;
for (i=arity-1; i>=0; i--){
DetermineSizeOfState (argstates[i],&asize, &bsize);
aindex += asize;
bindex += bsize;
PackArgument (argstates[i], aindex, bindex, asp_p, bsp, asize, bsize);
asp_p++;
}
}
void BuildTuple (int aindex,int bindex,int asp_p,int bsp,int arity,
States argstates,int asize,int bsize,int rootindex,FillKind fkind,Bool newnode)
{
MoveArgumentsFromBToA (arity, argstates, aindex, bindex, asp_p, bsp, asize, bsize);
if (newnode)
GenBuildh (&tuple_lab,arity);
else
GenFillh (&tuple_lab,arity,arity+asp_p-rootindex,fkind);
}
void BuildRecord (SymbDef record_sdef,int aindex,int bindex,int asp,int bsp,int asize,int bsize,int rootindex,FillKind fkind,Bool newnode)
{
LabDef record_lab;
ConvertSymbolToRLabel (&record_lab,record_sdef);
if (newnode)
GenBuildR (&record_lab,asize,bsize,asp-aindex,bsp-bindex,False);
else
GenFillR (&record_lab,asize,bsize,asp-rootindex,asp-aindex,bsp-bindex,fkind,False);
}
void PackArgument (StateS argstate,int aindex,int bindex,int asp,int bsp,int offasize,int offbsize)
{
if (IsSimpleState (argstate)){
if (argstate.state_kind==OnB)
BuildBasicFromB (argstate.state_object,bsp - bindex);
else
GenPushA (asp - aindex);
} else {
switch (argstate.state_type){
case TupleState:
BuildTuple (aindex, bindex, asp, bsp,argstate.state_arity, argstate.state_tuple_arguments,
offasize,offbsize,asp,NormalFill,True);
return;
case RecordState:
BuildRecord (argstate.state_record_symbol,aindex, bindex, asp, bsp,
offasize,offbsize,asp,NormalFill,True);
return;
case ArrayState:
GenBuildArray (asp - aindex);
return;
}
}
}
void CoerceArgumentOnTopOfStack (int *asp_p,int *bsp_p,StateS argstate,StateS nodestate,int asize,int bsize)
{
if (IsSimpleState (argstate) && argstate.state_kind==Undefined){
GenPopA (asize);
*asp_p-=asize;
GenPopB (bsize);
*bsp_p-=bsize;
} else if (IsSimpleState (nodestate)){
if (IsSimpleState (argstate)){
Coercions c;
c = CoerceStateKind (argstate.state_kind, nodestate.state_kind);
if (c==Reduce){
GenJsrEval (0);
c = CoerceStateKind (argstate.state_kind, StrictOnA);
}
switch (c){
case AToB:
PushBasicFromAOnB (argstate.state_object, 0);
*bsp_p+=ObjectSizes [argstate.state_object];
GenPopA (1);
*asp_p-=1;
return;
case BToA:
++*asp_p;
BuildBasicFromB (nodestate.state_object,0);
GenPopB (bsize);
*bsp_p-=bsize;
return;
case AToA:
case AToRoot:
return;
case BToB:
return;
default:
;
}
} else {
if (CoerceStateKind (StrictOnA, nodestate.state_kind)==Reduce)
GenJsrEval (0);
switch (argstate.state_type){
case TupleState: /* a tuple is demanded but not offered */
*asp_p-=1;
UnpackTuple (*asp_p,asp_p,bsp_p,True,argstate.state_arity, argstate.state_tuple_arguments);
break;
case RecordState:
*asp_p-=1;
UnpackRecord (*asp_p,asp_p,bsp_p,True,argstate.state_arity,argstate.state_record_arguments);
break;
case ArrayState:
UnpackArrayOnTopOfStack();
break;
}
}
} else if (IsSimpleState (argstate)){
/* a tuple or record is offered but not demanded */
switch (nodestate.state_type){
case TupleState:
BuildTuple (*asp_p,*bsp_p,*asp_p,*bsp_p,nodestate.state_arity,nodestate.state_tuple_arguments,
asize,bsize,*asp_p,NormalFill,True);
*asp_p+=1;
break;
case RecordState:
BuildRecord (nodestate.state_record_symbol,*asp_p,*bsp_p,*asp_p,*bsp_p,
asize,bsize,*asp_p,NormalFill,True);
*asp_p+=1;
break;
case ArrayState:
GenBuildArray (0);
++*asp_p;
break;
}
#if UPDATE_POP
GenUpdatePopA (0,asize);
#else
GenUpdateA (0,asize);
GenPopA (asize);
#endif
*asp_p-=asize;
GenPopB (bsize);
*bsp_p-=bsize;
} else {
if (argstate.state_type==TupleState)
AdjustTuple (asize,bsize,asp_p,bsp_p,argstate.state_arity,
argstate.state_tuple_arguments, nodestate.state_tuple_arguments,asize, bsize);
}
}
#define HasBeenReduced(c) ((c)==Reduce)
static void CopyArguments (States demstates,States offstates,int arity,int aindex,int bindex,int *asp_p,int *bsp,int aszie,int bsize);
static Bool CopyArgument (StateS demstate,StateS offstate,int aindex,int bindex,int *asp_p,int *bsp_p,int offasize,int offbsize,Bool newnode)
{
if (IsSimpleState (demstate) && demstate.state_kind==Undefined)
return False;
if (IsSimpleState (offstate)){
Bool leftontop;
Coercions c;
StateKind offkind;
offkind = offstate.state_kind;
c = CoerceSimpleStateArgument (demstate, offkind, aindex, asp_p, True, &leftontop);
offkind = AdjustStateKind (offkind, c);
if (IsSimpleState (demstate)){
StateKind demkind;
demkind = demstate.state_kind;
switch (CoerceStateKind (demkind, offkind)){
case AToB:
PushBasicFromAOnB (demstate.state_object, *asp_p - aindex);
*bsp_p += ObjectSizes [demstate.state_object];
if (leftontop){
GenPopA (1);
*asp_p -= SizeOfAStackElem;
}
break;
case BToA:
if (newnode){
++*asp_p;
BuildBasicFromB (offstate.state_object,*bsp_p - bindex);
} else
FillBasicFromB (offstate.state_object,*bsp_p - bindex,0,NormalFill);
break;
case BToB:
PushBasicOnB (demstate.state_object, *bsp_p - bindex);
*bsp_p += ObjectSizes [demstate.state_object];
break;
case AToA:
case AToRoot:
if (leftontop){
if (!newnode)
GenFillFromA (0, 1, NormalFill);
} else {
if (newnode){
GenPushA (*asp_p - aindex);
*asp_p += SizeOfAStackElem;
} else
GenFillFromA (*asp_p - aindex, 0, NormalFill);
}
break;
default:
break;
}
} else {
if (leftontop)
*asp_p -= SizeOfAStackElem;
switch (demstate.state_type){
case TupleState:
UnpackTuple (aindex, asp_p,bsp_p,leftontop, demstate.state_arity,demstate.state_tuple_arguments);
break;
case RecordState:
UnpackRecord (aindex, asp_p,bsp_p,leftontop, demstate.state_arity,demstate.state_record_arguments);
break;
case ArrayState:
UnpackArray (aindex, asp_p, leftontop);
break;
}
}
return HasBeenReduced (c);
}
else if (IsSimpleState (demstate)){
switch (offstate.state_type){
case TupleState:
BuildTuple (aindex, bindex, *asp_p, *bsp_p,offstate.state_arity, offstate.state_tuple_arguments,
offasize, offbsize, *asp_p, NormalFill,newnode);
if (newnode)
*asp_p += SizeOfAStackElem;
break;
case RecordState:
BuildRecord (offstate.state_record_symbol, aindex, bindex, *asp_p, *bsp_p,
offasize, offbsize, *asp_p, NormalFill, newnode);
if (newnode)
*asp_p += SizeOfAStackElem;
break;
case ArrayState:
if (newnode){
GenBuildArray (*asp_p - aindex);
++*asp_p;
} else
GenFillArray (*asp_p - aindex, 0, NormalFill);
break;
}
return False; /** to indicate that the offered object has not been changed **/
} else {
switch (offstate.state_type){
case TupleState:
CopyArguments (demstate.state_tuple_arguments,
offstate.state_tuple_arguments, demstate.state_arity,
aindex, bindex, asp_p, bsp_p, offasize, offbsize);
break;
case RecordState:
CopyArguments (demstate.state_record_arguments,
offstate.state_record_arguments, demstate.state_arity,
aindex, bindex, asp_p, bsp_p, offasize, offbsize);
break;
case ArrayState:
GenPushA (*asp_p - aindex);
*asp_p += SizeOfAStackElem;
break;
}
return False;
}
}
static void CopyArguments (States demstates,States offstates,int arity,int aindex,int bindex,int *asp_p,int *bsp_p,int asize,int bsize)
{
int i;
aindex-= asize;
bindex -= bsize;
for (i=arity-1; i>=0; i--){
DetermineSizeOfState (offstates[i],&asize, &bsize);
aindex += asize;
bindex += bsize;
CopyArgument (demstates[i],offstates[i],aindex,bindex,asp_p,bsp_p,asize,bsize,True);
}
}
static void CreateParallelCode (NodeDefs nds,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
switch (nds->def_node->node_annotation){
case ParallelAnnot:
case ParallelAtAnnot:
case ParallelNFAnnot:
if (nds->def_id->nid_mark & ON_A_CYCLE_MASK){
/* the channel has already been created */
GenSendGraph (GetReducerCode (nds->def_node->node_annotation), 0,*asp_p-nds->def_id->nid_a_index);
GenPopA (1);
*asp_p -= SizeOfAStackElem;
} else {
GenProcIdCalculation (nds->def_node,nds->def_node->node_annotation,asp_p,bsp_p,code_gen_node_ids_p);
GenCreateChannel (channel_code);
--*bsp_p;
GenSendGraph (GetReducerCode (nds->def_node->node_annotation), 1, 0);
GenUpdateA (0, 1);
GenPopA (1);
}
break;
case InterleavedAnnot:
GenNewInterleavedReducer (*asp_p-nds->def_id->nid_a_index, hnf_reducer_code);
break;
case ContinueAnnot:
if (get_p_at_node (nds->def_node)){
GenRedIdCalculation (get_p_at_node (nds->def_node),asp_p,bsp_p,code_gen_node_ids_p);
SetContinueOnReducer (*asp_p-nds->def_id->nid_a_index);
} else
SetContinue (*asp_p-nds->def_id->nid_a_index);
break;
case ContInterleavedAnnot:
GenNewContInterleavedReducer (*asp_p-nds->def_id->nid_a_index);
break;
case WaitAnnot:
GenSetRedId (*asp_p-nds->def_id->nid_a_index);
break;
case InterleavedNFAnnot:
GenNewInterleavedReducer (*asp_p-nds->def_id->nid_a_index, nf_reducer_code);
break;
}
}
void ChangeEvalStatusKindToStrictOnA (NodeId node_id,SavedNidStateS **saved_nid_state_l)
{
if (!IsSimpleState (node_id->nid_state))
error_in_function ("ChangeEvalStatusKindToStrictOnA");
if (saved_nid_state_l)
save_node_id_state (node_id,saved_nid_state_l);
node_id->nid_state__.state_kind = StrictOnA;
}
static void ChangeEvalStatusKind (NodeId noid, StateKind state)
{
if (noid){
if (!IsSimpleState (noid->nid_state))
error_in_function ("ChangeEvalStatusKind");
noid->nid_state__.state_kind = state;
}
}
static void ReduceSemiStrictNodes (const NodeDefs nds,int asp)
{
NodeDefs nd;
int has_parallel_state;
has_parallel_state=0;
for_l (nd,nds,def_next){
if (IsSimpleState (nd->def_id->nid_state)){
switch (nd->def_id->nid_state.state_kind){
case SemiStrict:
if (nd->def_node->node_state.state_mark & STATE_PARALLEL_MASK){
has_parallel_state=1;
continue;
}
ChangeEvalStatusKind (nd->def_id, StrictOnA);
/* evaluate strict annotated */
GenJsrEval (asp - nd->def_id->nid_a_index);
break;
case Parallel:
StaticMessage (False, "","parallel annotation ignored(?)");
break;
}
}
}
if (has_parallel_state)
for_l (nd,nds,def_next){
if (IsSimpleState (nd->def_id->nid_state)){
if (nd->def_id->nid_state.state_kind==SemiStrict){
ChangeEvalStatusKind (nd->def_id, StrictOnA);
/* evaluate strict annotated */
GenJsrEval (asp - nd->def_id->nid_a_index);
}
}
}
}
void BuildOrFillLazyFieldSelector (SymbDef selector_sdef,StateKind result_state_kind,int *asp_p,NodeId update_node_id)
{
LabDef nsellab,dsellab;
char *record_name;
int fill_arity;
SymbDef record_sdef;
StateS *field_result_state_p;
ConvertSymbolToDandNLabel (&dsellab,&nsellab,selector_sdef);
record_sdef=selector_sdef->sdef_type->type_lhs->ft_symbol->symb_def;
record_name=record_sdef->sdef_ident->ident_name;
field_result_state_p=&record_sdef->sdef_record_state.state_record_arguments [selector_sdef->sdef_sel_field_number];
fill_arity= IsSimpleState (*field_result_state_p) ? (field_result_state_p->state_kind!=OnB ? -4 : -3) : 1;
/* we use a negative arity to indicate lazy selectors */
if (update_node_id==NULL)
GenBuildFieldSelector (&dsellab,&nsellab,record_name,fill_arity);
else {
GenFillFieldSelector (&dsellab,&nsellab,record_name,fill_arity,*asp_p-update_node_id->nid_a_index,result_state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=1;
}
}
void ReplaceRecordOnTopOfStackByField (int *asp_p,int *bsp_p,int apos,int bpos,int asize,int bsize,int rec_a_size,int rec_b_size)
{
int i;
rec_a_size -= asize;
rec_b_size -= bsize;
for (i = asize - 1; i >= 0; i--)
#if UPDATE_POP
if (i==0)
GenUpdatePopA (apos,rec_a_size);
else
#endif
GenUpdateA (apos + i, rec_a_size + i);
for (i = bsize - 1; i >= 0; i--)
#if UPDATE_POP
if (i==0)
GenUpdatePopB (bpos,rec_b_size);
else
#endif
GenUpdateB (bpos + i, rec_b_size + i);
#if UPDATE_POP
if (asize==0)
#endif
GenPopA (rec_a_size);
*asp_p-=rec_a_size;
#if UPDATE_POP
if (bsize==0)
#endif
GenPopB (rec_b_size);
*bsp_p-=rec_b_size;
}
#define ResultIsNotInRootNormalForm(state) (IsLazyState (state) ||\
IsSimpleState (state) && (state).state_kind == LazyRedirection)
void add_node_id_to_list (struct node_id *node_id,NodeIdListElementS **node_ids_l)
{
NodeIdListElementP free_node_id;
free_node_id=CompAllocType (NodeIdListElementS);
free_node_id->nidl_node_id=node_id;
free_node_id->nidl_next=*node_ids_l;
*node_ids_l=free_node_id;
}
#if 0
# include "dbprint.h"
#endif
#if FREE_STRICT_LHS_TUPLE_ELEMENTS
static void add_node_id_or_tuple_node_ids_to_list (NodeIdP node_id,NodeIdListElementS **free_node_ids_l)
{
if (! (node_id->nid_node!=NULL && !IsSimpleState (node_id->nid_state)))
add_node_id_to_list (node_id,free_node_ids_l);
else {
ArgP arg_p;
for_l (arg_p,node_id->nid_node->node_arguments,arg_next){
NodeP arg_node_p;
arg_node_p=arg_p->arg_node;
if (arg_node_p->node_kind==NodeIdNode){
NodeIdP node_id_p;
node_id_p=arg_node_p->node_node_id;
if (node_id_p->nid_refcount==-1)
add_node_id_or_tuple_node_ids_to_list (node_id_p,free_node_ids_l);
}
}
}
}
#endif
void decrement_reference_count_of_node_id (struct node_id *node_id,NodeIdListElementS **free_node_ids_l)
{
int ref_count;
#if 0
printf ("decrement_reference_count_of_node_id ");
DPrintNodeId (node_id,StdOut);
printf ("\n");
#endif
ref_count=node_id->nid_refcount;
if (ref_count>0){
if (--ref_count==0)
add_node_id_to_list (node_id,free_node_ids_l);
node_id->nid_refcount=ref_count;
} else if (ref_count<-1){
++ref_count;
node_id->nid_refcount=ref_count;
if (ref_count==-1){
#if FREE_STRICT_LHS_TUPLE_ELEMENTS
if (unused_node_id_(node_id))
add_node_id_or_tuple_node_ids_to_list (node_id,free_node_ids_l);
#else
if (! (node_id->nid_node!=NULL && !IsSimpleState (node_id->nid_state)) && unused_node_id_(node_id)){
# if 0
printf ("add to free_node_ids list ");
DPrintNodeId (node_id,StdOut);
printf ("\n");
# endif
add_node_id_to_list (node_id,free_node_ids_l);
}
#endif
}
}
}
void DetermineFieldSizeAndPositionAndRecordSize
(int fieldnr,int *asize_p,int *bsize_p,int *apos_p,int *bpos_p,int *rec_asize_p,int *rec_bsize_p,StateS *record_state_p)
{
int i;
DetermineFieldSizeAndPosition (fieldnr,asize_p,bsize_p,apos_p,bpos_p,record_state_p->state_record_arguments);
*rec_asize_p = *asize_p + *apos_p;
*rec_bsize_p = *bsize_p + *bpos_p;
for (i=fieldnr+1; i<record_state_p->state_arity; ++i)
AddSizeOfState (record_state_p->state_record_arguments[i],rec_asize_p,rec_bsize_p);
}
int get_a_index_of_unpacked_lhs_node (ArgS *arg)
{
while (arg!=NULL){
int a_size,b_size;
DetermineSizeOfState (arg->arg_state,&a_size,&b_size);
if (a_size==0)
arg=arg->arg_next;
else {
Node arg_node;
arg_node=arg->arg_node;
if (arg_node->node_kind==NodeIdNode){
NodeId node_id;
node_id=arg->arg_node->node_node_id;
if (a_size!=0){
if (node_id->nid_refcount<0 && node_id->nid_state.state_type!=SimpleState && node_id->nid_node!=NULL)
arg=node_id->nid_node->node_arguments;
else
return node_id->nid_a_index;
}
} else
arg=arg_node->node_arguments;
}
}
return 0;
}
int get_b_index_of_unpacked_lhs_node (ArgS *arg)
{
while (arg!=NULL){
int a_size,b_size;
DetermineSizeOfState (arg->arg_state,&a_size,&b_size);
if (b_size==0)
arg=arg->arg_next;
else {
Node arg_node;
arg_node=arg->arg_node;
if (arg_node->node_kind==NodeIdNode){
NodeId node_id;
node_id=arg->arg_node->node_node_id;
if (node_id->nid_refcount<0 && node_id->nid_state.state_type!=SimpleState && node_id->nid_node!=NULL)
arg=node_id->nid_node->node_arguments;
else
return node_id->nid_b_index;
} else
arg=arg_node->node_arguments;
}
}
return 0;
}
Bool CopyNodeIdArgument (StateS demstate,NodeId node_id,int *asp_p,int *bsp_p)
{
int a_size,b_size,a_index,b_index;
DetermineSizeOfState (node_id->nid_state,&a_size,&b_size);
a_index=node_id->nid_a_index;
b_index=node_id->nid_b_index;
if (node_id->nid_refcount<0 && node_id->nid_state.state_type!=SimpleState && node_id->nid_node!=NULL){
ArgS *args;
args=node_id->nid_node->node_arguments;
if (a_size!=0)
a_index=get_a_index_of_unpacked_lhs_node (args);
if (b_size!=0)
b_index=get_b_index_of_unpacked_lhs_node (args);
}
return CopyArgument (demstate,node_id->nid_state,a_index,b_index,asp_p,bsp_p,a_size,b_size,True);
}
static void FillOrReduceFieldSelection (Node node,SymbDef seldef,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
Node arg_node;
Args arg;
int fieldnr;
arg = node->node_arguments;
fieldnr = seldef->sdef_sel_field_number;
arg_node=arg->arg_node;
if (node->node_arity>=SELECTOR_U){
if (IsLazyState (node->node_state)){
SymbDef new_select_sdef;
LabDef name,codelab;
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
new_select_sdef=create_select_function (node->node_symbol,node->node_arity);
ConvertSymbolToDandNLabel (&name,&codelab,new_select_sdef);
if (update_node_id==NULL)
GenBuild (&name,1,&codelab);
else {
GenFill (&name,1,&codelab,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
--*asp_p;
}
} else {
if (arg_node->node_kind!=NodeIdNode){
int asize,bsize,aindex,bindex;
StateP record_state_p;
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
record_state_p=&seldef->sdef_type->type_lhs->ft_symbol->symb_def->sdef_record_state;
DetermineFieldSizeAndPosition (fieldnr,&asize,&bsize,&aindex,&bindex,record_state_p->state_record_arguments);
if (node->node_arity<SELECTOR_L){
int n;
for (n=0; n<asize; ++n)
GenPushA (aindex+asize-1);
*asp_p+=asize;
for (n=0; n<bsize; ++n)
GenPushB (bindex+bsize-1);
*bsp_p+=bsize;
} else {
int record_a_size,record_b_size;
DetermineSizeOfState (*record_state_p,&record_a_size,&record_b_size);
ReplaceRecordOnTopOfStackByField (asp_p,bsp_p,aindex,bindex,asize,bsize,record_a_size,record_b_size);
}
} else {
int a_size,b_size,apos,bpos,record_a_size,record_b_size,n;
StateS tuple_state,tuple_state_arguments[2],*record_state_p;
NodeId arg_node_id;
arg_node_id=arg_node->node_node_id;
record_state_p=&seldef->sdef_type->type_lhs->ft_symbol->symb_def->sdef_record_state;
DetermineFieldSizeAndPositionAndRecordSize (fieldnr,&a_size,&b_size,&apos,&bpos,&record_a_size,&record_b_size,record_state_p);
CopyNodeIdArgument (*record_state_p,arg_node_id,asp_p,bsp_p);
for (n=0; n<a_size; ++n)
GenPushA (apos+a_size-1);
*asp_p+=a_size;
for (n=0; n<b_size; ++n)
GenPushB (bpos+b_size-1);
*bsp_p+=b_size;
tuple_state.state_type=TupleState;
tuple_state.state_arity=2;
tuple_state.state_tuple_arguments=tuple_state_arguments;
tuple_state_arguments[0]=record_state_p->state_record_arguments[fieldnr];
tuple_state_arguments[1]=*record_state_p;
CoerceArgumentOnTopOfStack (asp_p,bsp_p,tuple_state,node->node_state,record_a_size+a_size,record_b_size+b_size);
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
}
return;
}
if (arg_node->node_kind!=NodeIdNode){
if (IsLazyState (node->node_state)){
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
#ifdef DO_LAZY_SELECTORS_FROM_BOXED_STRICT_RECORDS
if (!ResultIsNotInRootNormalForm (arg_node->node_state) && update_node_id==NULL){
int asize,bsize,apos,bpos,tot_asize,tot_bsize;
StateP record_state_p,field_state_p;
record_state_p=&seldef->sdef_type->type_lhs->ft_symbol->symb_def->sdef_record_state;
if (record_state_p->state_type!=RecordState)
error_in_function ("FillOrReduceFieldSelection");
DetermineFieldSizeAndPositionAndRecordSize (fieldnr,&asize,&bsize,&apos,&bpos,&tot_asize,&tot_bsize,record_state_p);
GenPushRArgB (0,tot_asize,tot_bsize,bpos+1,bsize);
GenReplRArgA (tot_asize,tot_bsize,apos+1,asize);
*asp_p -= 1-asize;
*bsp_p += bsize;
field_state_p=&record_state_p->state_record_arguments [fieldnr];
CoerceArgumentOnTopOfStack (asp_p,bsp_p,node->node_state,*field_state_p,asize,bsize);
if (node->node_state.state_kind==OnA && !ResultIsNotInRootNormalForm (*field_state_p))
node->node_state.state_kind=StrictOnA;
} else
#endif
BuildOrFillLazyFieldSelector (seldef,node->node_state.state_kind,asp_p,update_node_id);
} else {
int asize,bsize,apos,bpos,tot_asize,tot_bsize;
Build (arg_node,asp_p,bsp_p,code_gen_node_ids_p);
DetermineFieldSizeAndPositionAndRecordSize (fieldnr,&asize,&bsize,&apos,&bpos,&tot_asize,&tot_bsize,&arg->arg_state);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,arg->arg_state,arg_node->node_state,tot_asize,tot_bsize);
ReplaceRecordOnTopOfStackByField (asp_p,bsp_p,apos,bpos,asize,bsize,tot_asize,tot_bsize);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,node->node_state,arg->arg_state.state_record_arguments[fieldnr],asize,bsize);
}
} else {
StateS recstate;
NodeId arg_node_id;
arg_node_id=arg_node->node_node_id;
recstate=arg_node_id->nid_state;
if (recstate.state_type==RecordState){
int a_size,b_size,apos,bpos,record_a_index,record_b_index;
StateP field_state_p;
DetermineFieldSizeAndPosition (fieldnr,&a_size,&b_size,&apos,&bpos,recstate.state_record_arguments);
if (arg_node_id->nid_refcount<0 && arg_node_id->nid_node!=NULL){
ArgS *args;
args=arg_node_id->nid_node->node_arguments;
record_a_index=get_a_index_of_unpacked_lhs_node (args);
record_b_index=get_b_index_of_unpacked_lhs_node (args);
} else {
record_a_index=arg_node_id->nid_a_index;
record_b_index=arg_node_id->nid_b_index;
}
field_state_p=&recstate.state_record_arguments[fieldnr];
if (update_node_id==NULL){
CopyArgument (node->node_state,*field_state_p,record_a_index-apos,record_b_index-bpos,asp_p,bsp_p,a_size,b_size,True);
} else {
int locasp;
locasp = *asp_p;
GenPushA (*asp_p-update_node_id->nid_a_index);
*asp_p+=1;
CopyArgument (node->node_state,*field_state_p,record_a_index-apos,record_b_index-bpos,asp_p,bsp_p,a_size,b_size,False);
GenPopA (*asp_p-locasp);
*asp_p=locasp;
}
#ifdef DO_LAZY_SELECTORS_FROM_BOXED_STRICT_RECORDS
if (node->node_state.state_type==SimpleState && node->node_state.state_kind==OnA && !ResultIsNotInRootNormalForm (*field_state_p))
node->node_state.state_kind=StrictOnA;
#endif
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
} else if (IsLazyState (node->node_state)){
#ifdef DO_LAZY_SELECTORS_FROM_BOXED_STRICT_RECORDS
if ((recstate.state_kind==StrictOnA || recstate.state_kind==StrictRedirection) && update_node_id==NULL){
int asize,bsize,apos,bpos,tot_asize,tot_bsize,recindex;
StateP record_state_p,field_state_p;
recindex = arg_node_id->nid_a_index;
record_state_p=&seldef->sdef_type->type_lhs->ft_symbol->symb_def->sdef_record_state;
if (record_state_p->state_type!=RecordState)
error_in_function ("FillOrReduceFieldSelection");
DetermineFieldSizeAndPositionAndRecordSize (fieldnr,&asize,&bsize,&apos,&bpos,&tot_asize,&tot_bsize,record_state_p);
GenPushRArgB (*asp_p-recindex,tot_asize,tot_bsize,bpos+1,bsize);
GenPushRArgA (*asp_p-recindex,tot_asize,tot_bsize,apos+1,asize);
*asp_p+=asize;
*bsp_p+=bsize;
field_state_p=&record_state_p->state_record_arguments [fieldnr];
CoerceArgumentOnTopOfStack (asp_p,bsp_p,node->node_state,*field_state_p,asize,bsize);
if (node->node_state.state_kind==OnA && !ResultIsNotInRootNormalForm (*field_state_p))
node->node_state.state_kind=StrictOnA;
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
} else
#endif
{
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
BuildOrFillLazyFieldSelector (seldef,node->node_state.state_kind,asp_p,update_node_id);
}
} else {
int a_size,b_size,apos, bpos, tot_asize, tot_bsize,recindex;
/* the selector is strict but the record is not */
recindex = arg_node_id->nid_a_index;
DetermineFieldSizeAndPositionAndRecordSize (fieldnr,&a_size,&b_size,&apos, &bpos,&tot_asize,&tot_bsize,&arg->arg_state);
if (ResultIsNotInRootNormalForm (recstate)){
GenJsrEval (*asp_p-recindex);
ChangeEvalStatusKindToStrictOnA (arg_node_id,code_gen_node_ids_p->saved_nid_state_l);
recstate.state_kind = StrictOnA;
}
GenPushRArgB (*asp_p-recindex, tot_asize, tot_bsize, bpos+1,b_size);
GenPushRArgA (*asp_p-recindex, tot_asize, tot_bsize, apos+1,a_size);
*asp_p+=a_size;
*bsp_p+=b_size;
recstate = arg->arg_state.state_record_arguments [fieldnr];
CoerceArgumentOnTopOfStack (asp_p,bsp_p, node->node_state, recstate,a_size,b_size);
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
}
}
void FillSelectSymbol (StateKind result_state_kind,int arity,int argnr,Args arg,int *asp_p,int *bsp_p,
NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
LabDef sellab, nsellab;
BuildLazyTupleSelectorLabel (&nsellab,arity,argnr);
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
sellab = nsellab;
sellab.lab_pref = d_pref;
/* we use a negative arity to indicate lazy selectors */
if (update_node_id==NULL)
GenBuild (&sellab,-1,&nsellab);
else {
GenFill (&sellab,-1,&nsellab,*asp_p-update_node_id->nid_a_index,result_state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=1;
}
}
#if defined (THUNK_LIFT_SELECTORS)
void FillSelectAndRemoveSymbol (StateKind result_state_kind,int arity,int argnr,Args arg,int *asp_p,int *bsp_p,
NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
LabDef sellab, nsellab;
BuildLazyTupleSelectorAndRemoveLabel (&nsellab,arity,argnr);
BuildArg (arg,asp_p,bsp_p,code_gen_node_ids_p);
sellab = nsellab;
sellab.lab_pref = d_pref;
/* we use a negative arity to indicate lazy selectors */
if (update_node_id==NULL)
GenBuild (&sellab,-1,&nsellab);
else {
GenFill (&sellab,-1,&nsellab,*asp_p-update_node_id->nid_a_index,result_state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=1;
}
}
#endif
#if OPTIMIZE_LAZY_TUPLE_RECURSION
extern int lazy_tuple_recursion;
extern void update_tuple_element_node (StateP state_p,int tuple_element_a_index,int *asp_p,int *bsp_p);
#endif
static void FillOrReduceSelectSymbol (Node node,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
Args arg;
int argnr;
arg = node->node_arguments;
argnr = node->node_arity;
if (arg->arg_node->node_kind!=NodeIdNode){
if (IsLazyState (node->node_state))
FillSelectSymbol (node->node_state.state_kind,node->node_symbol->symb_arity,argnr,arg,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
else {
Node argnode;
int asize,bsize;
argnode = arg->arg_node;
DetermineSizeOfState (argnode->node_state, &asize, &bsize);
Build (argnode,asp_p,bsp_p,code_gen_node_ids_p);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,arg->arg_state,argnode->node_state, asize, bsize);
}
} else {
StateS tupstate;
NodeId arg_node_id;
/* the tuple is shared */
arg_node_id=arg->arg_node->node_node_id;
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if ((arg_node_id->nid_mark2 & NID_CALL_VIA_LAZY_SELECTIONS_ONLY) && update_node_id==NULL){
int select_node_index;
select_node_index=arg_node_id->nid_a_index-argnr;
GenPushA (*asp_p-select_node_index);
++*asp_p;
return;
}
#endif
tupstate = arg_node_id->nid_state;
if (IsSimpleState (tupstate)){
if (IsLazyState (node->node_state)){
/* added 10-8-1999 */
if (!IsLazyStateKind (tupstate.state_kind)){
GenPushArg (*asp_p-arg_node_id->nid_a_index,node->node_symbol->symb_arity,argnr);
*asp_p+=1;
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
} else
/* */
#if defined (THUNK_LIFT_SELECTORS)
if (arg_node_id->nid_refcount>0 && (arg_node_id->nid_node_def->def_mark & NODE_DEF_SELECT_AND_REMOVE_MASK)!=0)
FillSelectAndRemoveSymbol (node->node_state.state_kind,node->node_symbol->symb_arity,argnr,arg,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
else
#endif
FillSelectSymbol (node->node_state.state_kind,node->node_symbol->symb_arity,argnr,arg,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
} else {
int arity,tupindex;
StateS selectstate;
/* the selector is strict but the tuple is not */
arity = arg->arg_state.state_arity;
tupindex = arg_node_id->nid_a_index;
selectstate = arg->arg_state.state_tuple_arguments[argnr-1];
if (ResultIsNotInRootNormalForm (tupstate)){
GenJsrEval (*asp_p-tupindex);
ChangeEvalStatusKindToStrictOnA (arg_node_id,code_gen_node_ids_p->saved_nid_state_l);
tupstate.state_kind = StrictOnA;
}
#if defined (THUNK_LIFT_SELECTORS)
if (node->node_number!=0){
char bits[MaxNodeArity+2];
int n;
GenPushArgsU (*asp_p-tupindex,arity,argnr);
if (argnr>1)
GenPopA (argnr-1);
*asp_p+=1;
for (n=0; n<=arity; ++n)
bits[n]='0';
bits[arity+1]='\0';
bits[argnr]='1';
GenBuildh (&nil_lab,0);
if (arity<=2)
GenFill1 (&tuple_lab,arity,*asp_p+1-tupindex,bits);
else
GenFill2 (&tuple_lab,arity,*asp_p+1-tupindex,bits);
} else {
GenPushArg (*asp_p-tupindex,arity,argnr);
*asp_p+=1;
}
#else
GenPushArg (*asp_p-tupindex,arity,argnr);
*asp_p+=1;
#endif
if (!ResultIsNotInRootNormalForm (selectstate))
GenJsrEval (0);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,selectstate,tupstate,1,0);
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if (update_node_id!=NULL)
update_tuple_element_node (&selectstate,update_node_id->nid_a_index,asp_p,bsp_p);
#endif
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
} else {
int a_size,b_size,i,argasize,argbsize,a_index,b_index;
StateS selectstate;
a_size=0;
b_size=0;
for (i=0; i<argnr-1; i++)
AddSizeOfState (tupstate.state_tuple_arguments[i],&a_size,&b_size);
if (IsSimpleState (arg->arg_state))
selectstate = arg->arg_state;
else
selectstate = arg->arg_state.state_tuple_arguments[i];
DetermineSizeOfState (tupstate.state_tuple_arguments[i],&argasize, &argbsize);
a_index=arg_node_id->nid_a_index;
b_index=arg_node_id->nid_b_index;
if (arg_node_id->nid_refcount<0 && arg_node_id->nid_node!=NULL){
ArgP args;
args=arg_node_id->nid_node->node_arguments;
a_index=get_a_index_of_unpacked_lhs_node (args);
b_index=get_b_index_of_unpacked_lhs_node (args);
}
if (update_node_id==NULL)
CopyArgument (selectstate,tupstate.state_tuple_arguments[i],
a_index - a_size,b_index - b_size,asp_p,bsp_p, argasize, argbsize, True);
else {
int locasp;
locasp = *asp_p;
GenPushA (*asp_p-update_node_id->nid_a_index);
++*asp_p;
CopyArgument (selectstate,tupstate.state_tuple_arguments[i],
a_index - a_size,b_index - b_size,asp_p,bsp_p, argasize, argbsize, False);
GenPopA (*asp_p-locasp);
*asp_p=locasp;
}
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
}
}
void DetermineArrayElemDescr (StateS elemstate,Label lab)
{
if (elemstate.state_type==SimpleState)
*lab = BasicDescriptors [elemstate.state_object];
else if (elemstate.state_type==RecordState){
ConvertSymbolToRLabel (lab,elemstate.state_record_symbol);
} else
*lab = BasicDescriptors [UnknownObj];
}
#define UNUSED_NODE_ID_INDEX 30000
#if 0
#include "dbprint.h"
#endif
void cleanup_stack
(int *asp_p,int *bsp_p,int a_size,int b_size,NodeIdListElementS **a_node_ids_l,NodeIdListElementS **b_node_ids_l,
NodeIdListElementS **free_node_ids_l,MovedNodeIdP *moved_node_ids_l,int compact_stack_ok)
{
NodeIdListElementP p_node_ids;
int asp,bsp;
int n_a_elements_popped;
if (DoDebug){
PrintComment ();
FPrintF (OutFile,compact_stack_ok ? "Remove unused stack elements" : "Remove unused stack elements without moving");
}
asp=*asp_p;
bsp=*bsp_p;
n_a_elements_popped=0;
#if 0
printf ("cleanup_stack a_node_ids ");
for_l (p_node_ids,*a_node_ids_l,nidl_next){
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf (" ");
}
printf ("\n");
#endif
#if 0
printf ("cleanup_stack b_node_ids ");
for_l (p_node_ids,*b_node_ids_l,nidl_next){
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf (" ");
}
printf ("\n");
#endif
p_node_ids=*a_node_ids_l;
while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==UNUSED_NODE_ID_INDEX){
#if 0
printf ("cleanup_stack00 ");
printf ("%s ",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
#endif
p_node_ids=p_node_ids->nidl_next;
}
if (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==asp && (unused_node_id (p_node_ids->nidl_node_id))){
int n_a_elements,n_b_elements;
n_a_elements=0;
n_b_elements=0;
do {
#if 0
printf ("cleanup_stack01 ");
printf ("%s ",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
#endif
AddSizeOfState (p_node_ids->nidl_node_id->nid_state,&n_a_elements,&n_b_elements);
/* free p_node_ids */
p_node_ids=p_node_ids->nidl_next;
while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==UNUSED_NODE_ID_INDEX){
#if 0
printf ("cleanup_stack02 ");
printf ("%s ",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
#endif
p_node_ids=p_node_ids->nidl_next;
}
} while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==asp-n_a_elements && (unused_node_id (p_node_ids->nidl_node_id)));
*a_node_ids_l=p_node_ids;
n_a_elements_popped=n_a_elements;
}
p_node_ids=*b_node_ids_l;
if (p_node_ids!=NULL && (unused_node_id (p_node_ids->nidl_node_id)) && p_node_ids->nidl_node_id->nid_b_index==bsp){
int n_a_elements,n_b_elements;
n_a_elements=0;
n_b_elements=0;
do {
AddSizeOfState (p_node_ids->nidl_node_id->nid_state,&n_a_elements,&n_b_elements);
/* free p_node_ids */
p_node_ids=p_node_ids->nidl_next;
} while (p_node_ids!=NULL && (unused_node_id (p_node_ids->nidl_node_id)) && p_node_ids->nidl_node_id->nid_b_index==bsp-n_b_elements);
*b_node_ids_l=p_node_ids;
if (n_b_elements!=0){
int i;
for (i=b_size-1; i>=0; --i)
#if UPDATE_POP
if (i==0)
GenUpdatePopB (0,n_b_elements);
else
#endif
GenUpdateB (i,i+n_b_elements);
#if UPDATE_POP
if (b_size==0)
#endif
GenPopB (n_b_elements);
*bsp_p-=n_b_elements;
}
}
if (compact_stack_ok){
NodeIdListElementP free_node_id,keep_node_ids;
int node_id_a_size,node_id_b_size;
int free_size,used_size,move_free_size,move_used_size;
node_id_a_size=0;
node_id_b_size=0;
asp=*asp_p-n_a_elements_popped;
for_l (free_node_id,*free_node_ids_l,nidl_next){
struct node_id *node_id;
node_id=free_node_id->nidl_node_id;
if (node_id->nid_a_index < asp)
AddSizeOfState (node_id->nid_state,&node_id_a_size,&node_id_b_size);
}
free_size=0;
used_size=0;
move_free_size=0;
move_used_size=0;
keep_node_ids=NULL;
p_node_ids=*a_node_ids_l;
while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==UNUSED_NODE_ID_INDEX){
#if 0
printf ("cleanup_stack03 ");
printf ("%s ",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
#endif
p_node_ids=p_node_ids->nidl_next;
}
#if 0
printf ("cleanup_stack1 ");
printf ("%s\n",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
if (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index!=asp){
printf ("asp=%d nid_a_index=%d ",asp,p_node_ids->nidl_node_id->nid_a_index);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
}
#endif
while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==asp){
int element_a_size,element_b_size;
struct node_id *node_id;
node_id=p_node_ids->nidl_node_id;
DetermineSizeOfState (node_id->nid_state,&element_a_size,&element_b_size);
#if 0
DPrintNodeId (node_id,StdOut);
printf ("\n");
#endif
if (unused_node_id (node_id)){
free_size+=element_a_size;
} else {
if (free_size+used_size > node_id_a_size+node_id_a_size)
break;
used_size+=element_a_size;
}
asp-=element_a_size;
p_node_ids=p_node_ids->nidl_next;
while (p_node_ids!=NULL && p_node_ids->nidl_node_id->nid_a_index==UNUSED_NODE_ID_INDEX){
#if 0
printf ("cleanup_stack11 ");
printf ("%s ",CurrentAltLabel.lab_symbol->sdef_ident->ident_name);
DPrintNodeId (p_node_ids->nidl_node_id,StdOut);
printf ("\n");
#endif
p_node_ids=p_node_ids->nidl_next;
}
if (free_size>=used_size){
move_free_size=free_size;
move_used_size=used_size;
keep_node_ids=p_node_ids;
}
}
if (move_free_size!=0){
NodeIdListElementP reversed_node_ids;
int move_a_offset;
int source_asp,dest_asp;
move_a_offset=move_free_size;
source_asp=*asp_p-n_a_elements_popped-(move_free_size+move_used_size);
dest_asp=source_asp;
reversed_node_ids=NULL;
p_node_ids=*a_node_ids_l;
while (p_node_ids!=keep_node_ids){
NodeIdListElementP next_p_node_ids;
next_p_node_ids=p_node_ids->nidl_next;
p_node_ids->nidl_next=reversed_node_ids;
reversed_node_ids=p_node_ids;
p_node_ids=next_p_node_ids;
}
while (reversed_node_ids!=NULL){
NodeIdListElementP next_reversed_node_ids;
int element_a_size,element_b_size;
MovedNodeIdP new_moved_node_id;
struct node_id *node_id;
node_id=reversed_node_ids->nidl_node_id;
if (node_id->nid_a_index!=UNUSED_NODE_ID_INDEX){
DetermineSizeOfState (node_id->nid_state,&element_a_size,&element_b_size);
new_moved_node_id=CompAllocType (MovedNodeIdS);
new_moved_node_id->mnid_node_id=node_id;
new_moved_node_id->mnid_a_stack_offset=node_id->nid_a_index;
new_moved_node_id->mnid_next=*moved_node_ids_l;
*moved_node_ids_l=new_moved_node_id;
#if 0
printf ("cleanup_stack2 ");
DPrintNodeId (node_id,StdOut);
printf ("\n");
#endif
if (unused_node_id (node_id)){
source_asp+=element_a_size;
node_id->nid_a_index_=UNUSED_NODE_ID_INDEX;
} else {
int n;
for (n=element_a_size; n!=0; --n){
++source_asp;
++dest_asp;
GenUpdateA (*asp_p+a_size-source_asp,*asp_p+a_size-dest_asp);
}
node_id->nid_a_index_=dest_asp;
}
}
next_reversed_node_ids=reversed_node_ids->nidl_next;
reversed_node_ids->nidl_next=p_node_ids;
p_node_ids=reversed_node_ids;
reversed_node_ids=next_reversed_node_ids;
}
*a_node_ids_l=p_node_ids;
/* *a_node_ids_l=keep_node_ids; */
n_a_elements_popped+=move_a_offset;
}
}
if (n_a_elements_popped!=0){
int i;
for (i=a_size-1; i>=0; --i)
#if UPDATE_POP
if (i==0)
GenUpdatePopA (0,n_a_elements_popped);
else
#endif
GenUpdateA (i,i+n_a_elements_popped);
#if UPDATE_POP
if (a_size==0)
#endif
GenPopA (n_a_elements_popped);
*asp_p-=n_a_elements_popped;
}
{
NodeIdListElementP free_node_id;
int nil_on_stack;
nil_on_stack=0;
asp=*asp_p;
for_l (free_node_id,*free_node_ids_l,nidl_next){
struct node_id *node_id;
node_id=free_node_id->nidl_node_id;
#if 0
printf ("cleanup_stack3 ");
DPrintNodeId (node_id,StdOut);
printf ("\n");
#endif
if (node_id->nid_a_index < asp){
int node_id_a_size,node_id_b_size,a_index;
DetermineSizeOfState (node_id->nid_state,&node_id_a_size,&node_id_b_size);
if (node_id_a_size>0){
a_index=asp+a_size-node_id->nid_a_index;
NodeIdComment (node_id);
while (node_id_a_size>0){
if (!nil_on_stack){
GenBuildh (&nil_lab,0);
nil_on_stack=1;
}
GenUpdateA (0,1+a_index);
++a_index;
--node_id_a_size;
}
}
}
}
*free_node_ids_l=free_node_id;
if (nil_on_stack)
GenPopA (1);
}
}
static void SubSizeOfState (StateS state,int *a_offset_p,int *b_offset_p);
static void SubSizeOfStates (int arity,States states,int *a_offset_p,int *b_offset_p)
{
for (; arity; arity--)
SubSizeOfState (states [arity-1],a_offset_p,b_offset_p);
}
static void SubSizeOfState (StateS state,int *a_offset_p,int *b_offset_p)
{
if (IsSimpleState (state)){
if (state.state_kind==OnB)
*b_offset_p -= ObjectSizes [state.state_object];
else if (state.state_kind != Undefined)
*a_offset_p -= 1;
} else {
switch (state.state_type){
case RecordState:
SubSizeOfStates (state.state_arity,state.state_record_arguments,a_offset_p,b_offset_p);
break;
case TupleState:
SubSizeOfStates (state.state_arity,state.state_tuple_arguments,a_offset_p,b_offset_p);
break;
case ArrayState:
*a_offset_p -= 1;
break;
}
}
}
static void SubSizeOfArguments (ArgS *args,int *a_offset_p,int *b_offset_p)
{
ArgS *arg;
for_l (arg,args,arg_next)
SubSizeOfState (arg->arg_state,a_offset_p,b_offset_p);
}
void DetermineSizeOfArguments (ArgS *args,int *a_offset_p,int *b_offset_p)
{
ArgS *arg;
*a_offset_p=0;
*b_offset_p=0;
for_l (arg,args,arg_next)
AddSizeOfState (arg->arg_state,a_offset_p,b_offset_p);
}
static void BuildLazyArgs (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p);
static Bool BuildNonParArgs (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p);
static void BuildParArgs (ArgS* args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p);
static void ReorderParallelAndNonParallelArgsWithResultNode (Args args,int *asize_p,int *bsize_p);
#define BETWEEN(l,h,v) ((unsigned)((v)-(l)) <= (unsigned)((h)-(l)))
static int ChangeArgumentNodeStatesIfStricter (Args offered_args,States demanded_states)
{
StateP demanded_state_p;
ArgP arg_p;
for_la (arg_p,demanded_state_p,offered_args,demanded_states,arg_next){
Node arg_node;
int node_kind;
arg_node=arg_p->arg_node;
node_kind=arg_node->node_kind;
if (node_kind!=NodeIdNode){
if (node_kind==NormalNode && (BETWEEN (int_denot,real_denot,arg_node->node_symbol->symb_kind) || arg_node->node_symbol->symb_kind==string_denot))
;
else
if (!FirstStateIsStricter (arg_node->node_state,*demanded_state_p))
return 1;
} else
if (!FirstStateIsStricter (arg_node->node_node_id->nid_state,*demanded_state_p))
return 1;
}
for_la (arg_p,demanded_state_p,offered_args,demanded_states,arg_next){
Node arg_node;
arg_node=arg_p->arg_node;
if (arg_node->node_kind==NormalNode &&
(BETWEEN (int_denot,real_denot,arg_node->node_symbol->symb_kind) || arg_node->node_symbol->symb_kind==string_denot)
){
arg_node->node_state=*demanded_state_p;
}
arg_p->arg_state=*demanded_state_p;
}
return 0;
}
void BuildArgsWithNewResultNode (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p,int *a_size_p,int *b_size_p)
{
BuildNonParArgs (args,asp_p,bsp_p,code_gen_node_ids_p);
NewEmptyNode (asp_p,-1);
BuildParArgs (args,asp_p,bsp_p,code_gen_node_ids_p);
ReorderParallelAndNonParallelArgsWithResultNode (args,a_size_p,b_size_p);
}
void BuildArgsWithResultNodeOnStack (Args args,NodeIdP free_unique_node_id,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p,int *a_size_p,int *b_size_p)
{
BuildNonParArgs (args,asp_p,bsp_p,code_gen_node_ids_p);
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
BuildParArgs (args,asp_p,bsp_p,code_gen_node_ids_p);
ReorderParallelAndNonParallelArgsWithResultNode (args,a_size_p,b_size_p);
}
#if OPTIMIZE_LAZY_TUPLE_RECURSION
extern LabDef d_indirection_lab,n_indirection_lab;
#endif
static void FillSymbol (Node node,SymbDef sdef,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
LabDef name;
int symbarity;
symbarity = sdef->sdef_kind==RECORDTYPE ? sdef->sdef_cons_arity : sdef->sdef_arity;
if (symbarity==node->node_arity){
switch (sdef->sdef_kind){
case IMPRULE:
case DEFRULE:
case SYSRULE:
if (IsLazyState (node->node_state)){
LabDef codelab;
ConvertSymbolToDandNLabel (&name,&codelab,sdef);
if (sdef->sdef_kind==IMPRULE && (sdef->sdef_rule->rule_mark & RULE_UNBOXED_LAZY_CALL)){
int a_size,b_size;
#ifndef OPTIMIZE_LAZY_TUPLE_RECURSION
if (update_node_id!=NULL)
error_in_function ("FillSymbol");
#endif
DetermineSizeOfArguments (node->node_arguments,&a_size,&b_size);
if (b_size!=0)
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
else
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if (update_node_id!=NULL){
if (a_size+b_size<=2){
if (b_size!=0){
GenFillU (&name,a_size,b_size,&codelab,*asp_p-update_node_id->nid_a_index);
*bsp_p -= b_size;
} else
GenFill (&name,a_size,&codelab,*asp_p-update_node_id->nid_a_index,NormalFill);
*asp_p-=a_size;
GenPushA (*asp_p-update_node_id->nid_a_index);
*asp_p+=1;
} else {
if (b_size!=0)
GenBuildU (&name,a_size,b_size,&codelab);
else
GenBuild (&name,a_size,&codelab);
*asp_p += 1-a_size;
*bsp_p -= b_size;
GenFill (&d_indirection_lab,-2,&n_indirection_lab,*asp_p-update_node_id->nid_a_index,NormalFill);
--*asp_p;
}
} else
#endif
{
*asp_p += 1-a_size;
*bsp_p -= b_size;
if (b_size!=0)
GenBuildU (&name,a_size,b_size,&codelab);
else
GenBuild (&name,a_size,&codelab);
}
return;
}
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (update_node_id==NULL){
*asp_p += 1-symbarity;
GenBuild (&name,symbarity,&codelab);
} else {
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if ((update_node_id->nid_mark & ON_A_CYCLE_MASK)!=0 || symbarity<=2){
GenFill (&name,symbarity,&codelab,*asp_p-update_node_id->nid_a_index,PartialFill);
*asp_p-=symbarity;
} else {
GenBuild (&name,symbarity,&codelab);
*asp_p+=1-symbarity;
GenFill (&d_indirection_lab,-2,&n_indirection_lab,*asp_p-update_node_id->nid_a_index,NormalFill);
--*asp_p;
}
#else
GenFill (&name,symbarity,&codelab,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p -= symbarity;
#endif
}
} else {
int newnode,a_size,b_size;
ConvertSymbolToLabel (&name,sdef);
newnode=False;
if (update_node_id==NULL && ExpectsResultNode (node->node_state)){
BuildArgsWithNewResultNode (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p,&a_size,&b_size);
*asp_p-=a_size;
*bsp_p-=b_size;
if (! (sdef->sdef_kind==SYSRULE
&& sdef->sdef_ident->ident_instructions!=NULL
&& *sdef->sdef_ident->ident_instructions!='\0'
&& *sdef->sdef_ident->ident_instructions!='.'))
{
cleanup_stack (asp_p,bsp_p,a_size,b_size,&code_gen_node_ids_p->a_node_ids,&code_gen_node_ids_p->b_node_ids,
&code_gen_node_ids_p->free_node_ids,code_gen_node_ids_p->moved_node_ids_l,
code_gen_node_ids_p->doesnt_fail);
}
CallFunction (&name,sdef,True,node);
AddSizeOfState (node->node_state,asp_p,bsp_p);
return;
}
DetermineSizeOfArguments (node->node_arguments,&a_size,&b_size);
if (update_node_id!=NULL && update_node_id->nid_a_index!=*asp_p){
GenPushA (*asp_p-update_node_id->nid_a_index);
*asp_p += SizeOfAStackElem;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
*asp_p-=a_size+1; /* changed 20-7-1999, was a_size */
*bsp_p-=b_size;
if (! (sdef->sdef_kind==SYSRULE
&& sdef->sdef_ident->ident_instructions!=NULL
&& *sdef->sdef_ident->ident_instructions!='\0'
&& *sdef->sdef_ident->ident_instructions!='.'))
{
cleanup_stack (asp_p,bsp_p,a_size+1,b_size,&code_gen_node_ids_p->a_node_ids,&code_gen_node_ids_p->b_node_ids,
&code_gen_node_ids_p->free_node_ids,code_gen_node_ids_p->moved_node_ids_l,
code_gen_node_ids_p->doesnt_fail);
}
CallFunction (&name,sdef,True,node);
AddSizeOfState (node->node_state,asp_p,bsp_p);
GenPopA (1);
*asp_p-=1;
} else {
if (newnode)
++a_size;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
*asp_p-=a_size;
*bsp_p-=b_size;
if (! (sdef->sdef_kind==SYSRULE
&& sdef->sdef_ident->ident_instructions!=NULL
&& *sdef->sdef_ident->ident_instructions!='\0'
&& *sdef->sdef_ident->ident_instructions!='.'))
{
cleanup_stack (asp_p,bsp_p,a_size,b_size,&code_gen_node_ids_p->a_node_ids,&code_gen_node_ids_p->b_node_ids,
&code_gen_node_ids_p->free_node_ids,code_gen_node_ids_p->moved_node_ids_l,
code_gen_node_ids_p->doesnt_fail);
}
CallFunction (&name,sdef,True,node);
AddSizeOfState (node->node_state,asp_p,bsp_p);
}
}
return;
case CONSTRUCTOR:
if (sdef->sdef_strict_constructor){
int lazy_fill;
ConvertSymbolToLabel (&name,sdef);
lazy_fill=IsLazyState (node->node_state);
if (lazy_fill)
lazy_fill=ChangeArgumentNodeStatesIfStricter (node->node_arguments,sdef->sdef_constructor->cl_state_p);
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (lazy_fill){
LabDef reclab, contlab;
ConvertSymbolToConstructorDandNLabel (&reclab,&contlab,sdef);
if (update_node_id==NULL){
*asp_p+=1-symbarity;
GenBuild (&reclab,symbarity,&contlab);
} else {
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if ((update_node_id->nid_mark & ON_A_CYCLE_MASK)!=0 || symbarity<=2){
GenFill (&reclab,symbarity,&contlab,*asp_p-update_node_id->nid_a_index,ReleaseAndFill);
*asp_p-=symbarity;
} else {
GenBuild (&reclab,symbarity,&contlab);
*asp_p+=1-symbarity;
GenFill (&d_indirection_lab,-2,&n_indirection_lab,*asp_p-update_node_id->nid_a_index,NormalFill);
--*asp_p;
}
#else
GenFill (&reclab,symbarity,&contlab,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill);
*asp_p-=symbarity;
#endif
}
} else {
int asize,bsize;
LabDef record_label;
DetermineSizeOfArguments (node->node_arguments,&asize,&bsize);
ConvertSymbolToKLabel (&record_label,sdef);
*asp_p-=asize;
*bsp_p-=bsize;
if (update_node_id==NULL){
GenBuildR (&record_label,asize,bsize,0,0,True);
*asp_p+=1;
} else {
GenFillR (&record_label,asize,bsize,*asp_p+asize-update_node_id->nid_a_index,0,0,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill,True);
}
}
} else {
ConvertSymbolToConstructorDLabel (&name,sdef);
BuildLazyArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (update_node_id==NULL){
*asp_p+=1-node->node_arity;
GenBuildh (&name,node->node_arity);
} else {
GenFillh (&name,node->node_arity,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill);
*asp_p-=node->node_arity;
}
}
return;
case RECORDTYPE:
ConvertSymbolToLabel (&name,sdef);
if (IsSimpleState (node->node_state)){
LabDef record_label;
int lazy_fill;
lazy_fill=sdef->sdef_strict_constructor && IsLazyState (node->node_state);
if (lazy_fill)
lazy_fill=ChangeArgumentNodeStatesIfStricter (node->node_arguments,sdef->sdef_record_state.state_record_arguments);
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (lazy_fill){
LabDef contlab;
ConvertSymbolToRecordDandNLabel (&record_label,&contlab,sdef);
if (update_node_id==NULL){
*asp_p+=1-symbarity;
GenBuild (&record_label,symbarity,&contlab);
} else {
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if ((update_node_id->nid_mark & ON_A_CYCLE_MASK)!=0 || symbarity<=2){
GenFill (&record_label,symbarity,&contlab,*asp_p-update_node_id->nid_a_index,ReleaseAndFill);
*asp_p-=symbarity;
} else {
GenBuild (&record_label,symbarity,&contlab);
*asp_p+=1-symbarity;
GenFill (&d_indirection_lab,-2,&n_indirection_lab,*asp_p-update_node_id->nid_a_index,NormalFill);
--*asp_p;
}
#else
GenFill (&record_label,symbarity,&contlab,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill);
*asp_p-=symbarity;
#endif
}
} else {
int asize,bsize;
ConvertSymbolToRLabel (&record_label,sdef);
DetermineSizeOfArguments (node->node_arguments,&asize,&bsize);
*asp_p-=asize;
*bsp_p-=bsize;
if (update_node_id==NULL){
*asp_p+=1;
GenBuildR (&record_label,asize,bsize,0,0,True);
} else {
GenFillR (&record_label,asize,bsize,*asp_p+asize-update_node_id->nid_a_index,0,0,node->node_state.state_kind==SemiStrict ? ReleaseAndFill : NormalFill,True);
}
}
} else
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
return;
default:
if (update_node_id==NULL)
NewEmptyNode (asp_p,-1);
return;
}
} else {
if (sdef->sdef_kind==CONSTRUCTOR)
ConvertSymbolToConstructorDLabel (&name,sdef);
else
ConvertSymbolToDLabel (&name,sdef);
/* Symbol has too few arguments */
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (update_node_id==NULL){
*asp_p+=1-node->node_arity;
GenBuildh (&name,node->node_arity);
} else {
GenFillh (&name,node->node_arity,*asp_p-update_node_id->nid_a_index,NormalFill);
*asp_p-=node->node_arity;
}
}
}
void GenTypeError (void)
{
GenDAStackLayout (0);
GenJsr (&type_error_lab);
GenOAStackLayout (0);
TypeErrorFound = True;
}
static void decrement_reference_count_of_node_ids_in_graph (Node node,NodeIdListElementS **free_node_ids_l)
{
if (node->node_kind!=NodeIdNode){
struct arg *arg;
for_l (arg,node->node_arguments,arg_next)
decrement_reference_count_of_node_ids_in_graph (arg->arg_node,free_node_ids_l);
} else
decrement_reference_count_of_node_id (node->node_node_id,free_node_ids_l);
}
static void increment_reference_count_of_node_ids_in_graph (Node node)
{
if (node->node_kind!=NodeIdNode){
struct arg *arg;
for_l (arg,node->node_arguments,arg_next)
increment_reference_count_of_node_ids_in_graph (arg->arg_node);
} else {
struct node_id *node_id;
int ref_count;
node_id=node->node_node_id;
ref_count=node_id->nid_refcount;
if (ref_count>=0)
node_id->nid_refcount=ref_count+1;
else
node_id->nid_refcount=ref_count-1;
}
}
#ifdef FASTER_STRICT_IF
static void build_strict_then_or_else (Node then_or_else_node,Node else_node,int *asp_p,int *bsp_p,
CodeGenNodeIdsP code_gen_node_ids_p,StateS result_state)
{
if (then_or_else_node->node_kind!=NodeIdNode){
SavedNidStateP saved_node_id_states;
struct code_gen_node_ids code_gen_node_ids;
MovedNodeIdP moved_node_ids;
int a_size,b_size;
saved_node_id_states=NULL;
moved_node_ids=NULL;
code_gen_node_ids.free_node_ids=code_gen_node_ids_p->free_node_ids;
code_gen_node_ids.saved_nid_state_l=&saved_node_id_states;
code_gen_node_ids.doesnt_fail=False;
code_gen_node_ids.moved_node_ids_l=&moved_node_ids;
code_gen_node_ids.a_node_ids=code_gen_node_ids_p->a_node_ids;
code_gen_node_ids.b_node_ids=code_gen_node_ids_p->b_node_ids;
if (else_node!=NULL)
decrement_reference_count_of_node_ids_in_graph (else_node,&code_gen_node_ids.free_node_ids);
Build (then_or_else_node,asp_p,bsp_p,&code_gen_node_ids);
if (else_node!=NULL)
increment_reference_count_of_node_ids_in_graph (else_node);
restore_saved_node_id_states (saved_node_id_states);
DetermineSizeOfState (then_or_else_node->node_state,&a_size,&b_size);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,result_state,then_or_else_node->node_state,a_size,b_size);
} else {
NodeId nid;
int a_size,b_size;
nid=then_or_else_node->node_node_id;
DetermineSizeOfState (nid->nid_state,&a_size,&b_size);
CopyArgument (result_state,nid->nid_state,nid->nid_a_index,nid->nid_b_index,asp_p,bsp_p,a_size,b_size,True);
}
}
static void fill_strict_if_node (Node node,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
StateS condition_result_state;
LabDef else_label,endif_label;
Args arguments,then_arg,else_arg;
int else_asp,else_bsp;
arguments = node->node_arguments;
SetUnaryState (&condition_result_state,OnB,BoolObj);
EvaluateCondition (arguments->arg_node,asp_p,bsp_p,code_gen_node_ids_p,condition_result_state);
MakeLabel (&else_label,"else",NewLabelNr,no_pref);
MakeLabel (&endif_label,"endif",NewLabelNr++,no_pref);
GenJmpFalse (&else_label);
then_arg=arguments->arg_next;
else_arg=then_arg->arg_next;
else_asp=*asp_p;
else_bsp=*bsp_p;
build_strict_then_or_else (then_arg->arg_node,else_arg->arg_node,asp_p,bsp_p,code_gen_node_ids_p,node->node_state);
GenJmp (&endif_label);
GenLabelDefinition (&else_label);
build_strict_then_or_else (else_arg->arg_node,NULL,&else_asp,&else_bsp,code_gen_node_ids_p,node->node_state);
if (else_asp!=*asp_p || else_bsp!=*bsp_p){
int a_size,b_size;
DetermineSizeOfState (node->node_state,&a_size,&b_size);
if (else_asp>*asp_p){
int difference,i;
difference=else_asp - *asp_p;
for (i=a_size-1; i>=0; --i)
#if UPDATE_POP
if (i==0)
GenUpdatePopA (0,difference);
else
#endif
GenUpdateA (i,i+difference);
#if UPDATE_POP
if (a_size==0)
#endif
GenPopA (difference);
} else if (else_asp<*asp_p){
int difference,i;
difference=*asp_p - else_asp;
if (difference>a_size){
int n;
GenBuildh (&nil_lab,0);
n=(difference-a_size)-1;
for (i=0; i<n; ++i)
GenPushA (i);
for (i=a_size-1; i>=0; --i)
GenPushA (difference-1);
if (a_size>0){
GenBuildh (&nil_lab,0);
for (i=0; i<a_size; ++i)
GenUpdateA (0,difference+i);
GenPopA (1);
}
} else {
for (i=difference-1; i>=0; --i)
GenPushA (difference-1);
if (difference<a_size){
GenBuildh (&nil_lab,0);
for (i=difference; i<a_size; ++i){
GenUpdateA (i+difference+1,i+1);
GenUpdateA (0,i+difference+1);
}
GenPopA (1);
}
}
}
if (else_bsp>*bsp_p){
int difference,i;
difference=else_bsp - *bsp_p;
for (i=b_size-1; i>=0; --i)
#if UPDATE_POP
if (i==0)
GenUpdatePopB (0,difference);
else
#endif
GenUpdateB (i,i+difference);
#if UPDATE_POP
if (b_size==0)
#endif
GenPopB (difference);
} else if (else_bsp<*bsp_p){
int difference,i;
SymbValue sv;
sv.val_int="0";
difference=*bsp_p - else_bsp;
if (difference>b_size){
int n;
PushBasic (IntObj,sv);
n=(difference-b_size)-1;
for (i=0; i<n; ++i)
GenPushB (i);
for (i=b_size-1; i>=0; --i)
GenPushB (difference-1);
if (b_size>0){
PushBasic (IntObj,sv);
for (i=0; i<b_size; ++i)
GenUpdateB (0,difference+i);
GenPopB (1);
}
} else {
for (i=difference-1; i>=0; --i)
GenPushB (difference-1);
if (difference<b_size){
PushBasic (IntObj,sv);
for (i=difference; i<b_size; ++i){
GenUpdateB (i+difference+1,i+1);
GenUpdateB (0,i+difference+1);
}
GenPopB (1);
}
}
}
}
{
int result_a_size,result_b_size;
DetermineSizeOfState (node->node_state,&result_a_size,&result_b_size);
if (code_gen_node_ids_p->a_node_ids!=NULL){
int asp_without_result;
NodeIdListElementP a_node_ids,a_node_id_p;
asp_without_result=*asp_p-result_a_size;
a_node_ids=code_gen_node_ids_p->a_node_ids;
/* JVG: changed 28-10-1999 */
a_node_id_p=a_node_ids;
while (a_node_id_p!=NULL && a_node_id_p->nidl_node_id->nid_a_index>asp_without_result)
if (a_node_id_p->nidl_node_id->nid_a_index!=UNUSED_NODE_ID_INDEX){
a_node_id_p=a_node_id_p->nidl_next;
a_node_ids=a_node_id_p;
} else
a_node_id_p=a_node_id_p->nidl_next;
/*
while (a_node_ids!=NULL &&
a_node_ids->nidl_node_id->nid_a_index>asp_without_result && a_node_ids->nidl_node_id->nid_a_index!=UNUSED_NODE_ID_INDEX)
{
a_node_ids=a_node_ids->nidl_next;
}
*/
code_gen_node_ids_p->a_node_ids=a_node_ids;
}
if (code_gen_node_ids_p->b_node_ids!=NULL){
int bsp_without_result;
NodeIdListElementP b_node_ids,b_node_id_p;
bsp_without_result=*bsp_p-result_b_size;
b_node_ids=code_gen_node_ids_p->b_node_ids;
/* JVG: changed 28-10-1999 */
b_node_id_p=b_node_ids;
while (b_node_id_p!=NULL && b_node_id_p->nidl_node_id->nid_b_index>bsp_without_result)
if (b_node_id_p->nidl_node_id->nid_b_index!=UNUSED_NODE_ID_INDEX){
b_node_id_p=b_node_id_p->nidl_next;
b_node_ids=b_node_id_p;
} else
b_node_id_p=b_node_id_p->nidl_next;
/*
while (b_node_ids!=NULL &&
b_node_ids->nidl_node_id->nid_b_index>bsp_without_result && b_node_ids->nidl_node_id->nid_b_index!=UNUSED_NODE_ID_INDEX)
{
b_node_ids=b_node_ids->nidl_next;
}
*/
code_gen_node_ids_p->b_node_ids=b_node_ids;
}
}
GenLabelDefinition (&endif_label);
}
#endif
static void FillNormalNode (Node node,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
Symbol symb;
symb = node->node_symbol;
switch (symb->symb_kind){
case definition:
FillSymbol (node,symb->symb_def,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
return;
case select_symb:
FillOrReduceSelectSymbol (node,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
return;
case apply_symb:
FillSymbol (node,ApplyDef,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
return;
case if_symb:
#ifdef FASTER_STRICT_IF
if (node->node_arity==3 && !IsLazyState (node->node_state) && update_node_id==NULL)
fill_strict_if_node (node,asp_p,bsp_p,code_gen_node_ids_p);
else
#endif
FillSymbol (node,IfDef,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
return;
case tuple_symb:
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (IsSimpleState (node->node_state)){
if (update_node_id==NULL){
*asp_p+=1-node->node_arity;
GenBuildh (&tuple_lab,node->node_arity);
} else {
GenFillh (&tuple_lab,node->node_arity,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind == SemiStrict ? ReleaseAndFill : NormalFill);
*asp_p-=node->node_arity;
}
}
return;
case cons_symb:
BuildLazyArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (update_node_id==NULL){
*asp_p+=1-node->node_arity;
GenBuildh (&cons_lab,node->node_arity);
} else {
GenFillh (&cons_lab, node->node_arity,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind == SemiStrict ? ReleaseAndFill : NormalFill);
*asp_p-=node->node_arity;
}
return;
case nil_symb:
if (update_node_id==NULL){
*asp_p+=1;
GenBuildh (&nil_lab,node->node_arity);
} else
GenFillh (&nil_lab,node->node_arity,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind == SemiStrict ? ReleaseAndFill : NormalFill);
return;
case string_denot:
GenBuildString (symb->symb_val);
*asp_p+=1;
if (IsSimpleState (node->node_state)){
if (update_node_id==NULL){
GenBuildh (&BasicDescriptors[ArrayObj],1);
} else {
GenFillh (&BasicDescriptors[ArrayObj],1,*asp_p-update_node_id->nid_a_index,ReleaseAndFill);
*asp_p-=1;
}
}
return;
default:
if (symb->symb_kind<Nr_Of_Basic_Types){
if (update_node_id==NULL){
*asp_p+=1;
GenBuildh (&BasicDescriptors[symb->symb_kind],0);
} else
GenFillh (&BasicDescriptors[symb->symb_kind],0,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind == SemiStrict ? ReleaseAndFill : NormalFill);
} else {
ObjectKind denottype;
denottype = (symb->symb_kind < Nr_Of_Predef_Types)
? BasicSymbolStates [symb->symb_kind].state_object
: UnknownObj;
if (node->node_state.state_object==denottype ||
node->node_state.state_object==UnknownObj || denottype==UnknownObj
#if ABSTRACT_OBJECT
|| node->node_state.state_object==AbstractObj || denottype==AbstractObj
#endif
)
{
if (node->node_state.state_kind==OnB){
*bsp_p += ObjectSizes [denottype];
PushBasic (denottype, symb->symb_val);
} else {
if (update_node_id==NULL){
*asp_p+=1;
BuildBasic (denottype,symb->symb_val);
} else {
FillBasic (denottype,symb->symb_val,*asp_p-update_node_id->nid_a_index,
node->node_state.state_kind == SemiStrict ? ReleaseAndFill : NormalFill);
}
}
} else {
StaticMessage (False,CurrentAltLabel.lab_symbol->sdef_ident->ident_name,Co_Wtype);
GenTypeError();
}
}
}
}
void RemoveSelectorsFromUpdateNode (ArgS *previous_arg,ArgS *arg)
{
while (arg!=NULL){
ArgS *field_arg;
field_arg=arg->arg_node->node_arguments;
previous_arg->arg_next=field_arg;
previous_arg=field_arg;
arg=arg->arg_next;
}
previous_arg->arg_next=NULL;
}
void UpdateNodeAndAddSelectorsToUpdateNode
(ArgS *record_arg,ArgS *first_field_arg,StateS *field_states,int record_a_size,int record_b_size,int *asp_p,int *bsp_p)
{
ArgS *arg,*previous_arg;
int a_offset,b_offset,arg_a_offset,arg_b_offset,previous_field_number;
a_offset=0;
b_offset=0;
arg_a_offset=record_a_size;
arg_b_offset=record_b_size;
previous_field_number=0;
previous_arg=record_arg;
for_l (arg,first_field_arg,arg_next){
int field_number,arg_a_size,arg_b_size;
Node field_node;
field_node=arg->arg_node;
field_node->node_arguments->arg_next=NULL;
field_number=field_node->node_symbol->symb_def->sdef_sel_field_number;
while (field_number!=previous_field_number){
AddSizeOfState (field_states[previous_field_number],&a_offset,&b_offset);
++previous_field_number;
}
DetermineSizeOfState (field_states[field_number],&arg_a_size,&arg_b_size);
while (arg_a_size){
GenUpdateA (arg_a_offset,a_offset);
++arg_a_offset;
++a_offset;
--arg_a_size;
}
while (arg_b_size){
GenUpdateB (arg_b_offset,b_offset);
++arg_b_offset;
++b_offset;
--arg_b_size;
}
++previous_field_number;
previous_arg->arg_next=arg;
previous_arg=arg;
}
previous_arg->arg_next=NULL;
if (arg_a_offset!=record_a_size){
a_offset=record_a_size;
while (a_offset>0){
--a_offset;
--arg_a_offset;
#if UPDATE_POP
if (a_offset==0)
GenUpdatePopA (a_offset,arg_a_offset);
else
#endif
GenUpdateA (a_offset,arg_a_offset);
}
#if UPDATE_POP
if (record_a_size==0)
#endif
GenPopA (arg_a_offset);
*asp_p -= arg_a_offset;
}
if (arg_b_offset!=record_b_size){
b_offset=record_b_size;
while (b_offset>0){
--b_offset;
--arg_b_offset;
#if UPDATE_POP
if (b_offset==0)
GenUpdatePopB (b_offset,arg_b_offset);
else
#endif
GenUpdateB (b_offset,arg_b_offset);
}
#if UPDATE_POP
if (record_b_size==0)
#endif
GenPopB (arg_b_offset);
*bsp_p -= arg_b_offset;
}
}
#ifdef DESTRUCTIVE_RECORD_UPDATES
void compute_bits_and_add_selectors_to_update_node
(ArgS *record_arg,ArgS *first_field_arg,StateS *field_states,int record_a_size,int record_b_size,
char bits[],int *n_a_fill_bits_p,int *n_b_fill_bits_p)
{
ArgP arg,previous_arg;
int a_offset,b_offset,previous_field_number;
unsigned int a_bits,b_bits,n,arg_n,n_args;
int n_a_fill_bits,n_b_fill_bits;
a_bits=0;
b_bits=0;
n_a_fill_bits=0;
n_b_fill_bits=0;
a_offset=0;
b_offset=0;
previous_field_number=0;
previous_arg=record_arg;
for_l (arg,first_field_arg,arg_next){
int field_number,arg_a_size,arg_b_size;
Node field_node;
field_node=arg->arg_node;
field_node->node_arguments->arg_next=NULL;
field_number=field_node->node_symbol->symb_def->sdef_sel_field_number;
while (field_number!=previous_field_number){
AddSizeOfState (field_states[previous_field_number],&a_offset,&b_offset);
++previous_field_number;
}
DetermineSizeOfState (field_states[field_number],&arg_a_size,&arg_b_size);
a_bits |= (~((~0)<<arg_a_size))<<a_offset;
b_bits |= (~((~0)<<arg_b_size))<<b_offset;
n_a_fill_bits+=arg_a_size;
n_b_fill_bits+=arg_b_size;
a_offset+=arg_a_size;
b_offset+=arg_b_size;
++previous_field_number;
previous_arg->arg_next=arg;
previous_arg=arg;
}
previous_arg->arg_next=NULL;
bits[0]='0';
for (n=0; n<record_a_size; ++n){
if (a_bits & (1<<n))
bits[n+1]='1';
else
bits[n+1]='0';
}
for (n=0; n<record_b_size; ++n){
if (b_bits & (1<<n))
bits[n+record_a_size+1]='1';
else
bits[n+record_a_size+1]='0';
}
bits[record_a_size+record_b_size+1]='\0';
*n_a_fill_bits_p=n_a_fill_bits;
*n_b_fill_bits_p=n_b_fill_bits;
}
#endif
static void FillUpdateNode (Node node,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
ArgS *record_arg,*first_field_arg;
int record_a_size,record_b_size;
record_arg=node->node_arguments;
first_field_arg=record_arg->arg_next;
RemoveSelectorsFromUpdateNode (record_arg,first_field_arg);
if (IsSimpleState (node->node_state)){
int n_arguments;
LabDef name,codelab;
SymbDef new_update_sdef;
struct node *record_node;
#if DESTRUCTIVE_RECORD_UPDATES
int update_immediately;
StateP record_node_id_state_p;
record_node=record_arg->arg_node;
if (node->node_state.state_kind==StrictOnA){
update_immediately=1;
record_node_id_state_p=&node->node_symbol->symb_def->sdef_record_state;
} else {
update_immediately=0;
if (record_node->node_kind==NodeIdNode){
record_node_id_state_p=&record_node->node_node_id->nid_state;
if (record_node_id_state_p->state_type==RecordState){
update_immediately=1;
if (record_node_id_state_p->state_record_symbol->sdef_strict_constructor){
StateS *record_states;
record_states=record_node_id_state_p->state_record_arguments;
if (!FieldArgumentNodeStatesAreStricter (record_arg->arg_next,first_field_arg,record_states))
update_immediately=0;
else {
ArgP node_arg,field_arg;
for_ll (node_arg,field_arg,record_arg->arg_next,first_field_arg,arg_next,arg_next){
Node arg_node;
int field_number;
field_number=field_arg->arg_node->node_symbol->symb_def->sdef_sel_field_number;
arg_node=node_arg->arg_node;
if (arg_node->node_kind==NormalNode &&
(BETWEEN (int_denot,real_denot,arg_node->node_symbol->symb_kind) || arg_node->node_symbol->symb_kind==string_denot))
{
arg_node->node_state=record_states[field_number];
}
node_arg->arg_state=record_states[field_number];
}
}
}
}
}
}
if (update_immediately){
if (node->node_state.state_kind==StrictOnA && record_node->node_kind==NodeIdNode){
NodeIdP record_node_id;
record_node_id=record_node->node_node_id;
if ((record_node_id->nid_state.state_mark & STATE_UNIQUE_MASK)!=0 &&
(record_node_id->nid_mark2 & NID_HAS_REFCOUNT_WITHOUT_UPDATES)!=0 &&
record_node_id->nid_number== -1 &&
record_node_id->nid_state.state_type==SimpleState &&
record_node_id->nid_state.state_kind==StrictOnA &&
update_node_id==NULL)
{
int n_a_fill_bits,n_b_fill_bits;
char bits[MaxNodeArity+2];
LabDef record_lab;
BuildArgs (record_arg->arg_next,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (*record_node_id_state_p,&record_a_size,&record_b_size);
compute_bits_and_add_selectors_to_update_node (record_arg,first_field_arg,
record_node_id_state_p->state_record_arguments,record_a_size,record_b_size,
bits,&n_a_fill_bits,&n_b_fill_bits);
ConvertSymbolToRLabel (&record_lab,record_node_id_state_p->state_record_symbol);
if (record_a_size+record_b_size>2)
GenFill2R (&record_lab,record_a_size,record_b_size,*asp_p-record_node_id->nid_a_index,bits);
else
GenFill1R (&record_lab,record_a_size,record_b_size,*asp_p-record_node_id->nid_a_index,bits);
*asp_p-=n_a_fill_bits;
*bsp_p-=n_b_fill_bits;
GenPushA (*asp_p-record_node_id->nid_a_index);
*asp_p+=1;
decrement_reference_count_of_node_id (record_node_id,&code_gen_node_ids_p->free_node_ids);
return;
}
}
record_arg->arg_state=*record_node_id_state_p;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (*record_node_id_state_p,&record_a_size,&record_b_size);
UpdateNodeAndAddSelectorsToUpdateNode (record_arg,first_field_arg,
record_node_id_state_p->state_record_arguments,record_a_size,record_b_size,asp_p,bsp_p);
if (update_node_id==NULL){
BuildRecord (record_node_id_state_p->state_record_symbol,*asp_p,*bsp_p,*asp_p,*bsp_p,record_a_size,record_b_size,
0,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill,True);
*asp_p+=1;
GenUpdateA (0,record_a_size);
} else
BuildRecord (record_node_id_state_p->state_record_symbol,*asp_p,*bsp_p,*asp_p,*bsp_p,record_a_size,record_b_size,
*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill,False);
GenPopA (record_a_size);
*asp_p-=record_a_size;
GenPopB (record_b_size);
*bsp_p-=record_b_size;
return;
}
#else
record_node=record_arg->arg_node;
if (record_node->node_kind==NodeIdNode){
StateP record_node_id_state_p;
record_node_id_state_p=&record_node->node_node_id->nid_state;
if (record_node_id_state_p->state_type==SimpleState && record_node_id_state_p->state_kind==StrictOnA)
record_node_id_state_p=&node->node_symbol->symb_def->sdef_record_state;
if (record_node_id_state_p->state_type==RecordState){
int update_immediately;
update_immediately=1;
if (record_node_id_state_p->state_record_symbol->sdef_strict_constructor){
StateP record_states;
record_states=record_node_id_state_p->state_record_arguments;
if (!FieldArgumentNodeStatesAreStricter (record_arg->arg_next,first_field_arg,record_states))
update_immediately=0;
else {
ArgP node_arg,field_arg;
for_ll (node_arg,field_arg,record_arg->arg_next,first_field_arg,arg_next,arg_next){
Node arg_node;
int field_number;
field_number=field_arg->arg_node->node_symbol->symb_def->sdef_sel_field_number;
arg_node=node_arg->arg_node;
if (arg_node->node_kind==NormalNode &&
(BETWEEN (int_denot,real_denot,arg_node->node_symbol->symb_kind) || arg_node->node_symbol->symb_kind==string_denot))
{
arg_node->node_state=record_states[field_number];
}
node_arg->arg_state=record_states[field_number];
}
}
}
if (update_immediately){
record_arg->arg_state=*record_node_id_state_p;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (*record_node_id_state_p,&record_a_size,&record_b_size);
UpdateNodeAndAddSelectorsToUpdateNode (record_arg,first_field_arg,
record_node_id_state_p->state_record_arguments,record_a_size,record_b_size,asp_p,bsp_p);
if (update_node_id==NULL){
BuildRecord (record_node_id_state_p->state_record_symbol,*asp_p,*bsp_p,*asp_p,*bsp_p,record_a_size,record_b_size,
0,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill,True);
*asp_p+=1;
GenUpdateA (0,record_a_size);
} else
BuildRecord (record_node_id_state_p->state_record_symbol,*asp_p,*bsp_p,*asp_p,*bsp_p,record_a_size,record_b_size,
*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill,False);
GenPopA (record_a_size);
*asp_p-=record_a_size;
GenPopB (record_b_size);
*bsp_p-=record_b_size;
return;
}
}
}
#endif
n_arguments=node->node_arity;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
new_update_sdef=CreateUpdateFunction (record_arg,first_field_arg,node);
ConvertSymbolToDandNLabel (&name,&codelab,new_update_sdef);
if (update_node_id==NULL){
GenBuild (&name,n_arguments,&codelab);
*asp_p+=1-n_arguments;
} else {
GenFill (&name,n_arguments,&codelab,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=n_arguments;
}
} else {
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (node->node_state,&record_a_size,&record_b_size);
UpdateNodeAndAddSelectorsToUpdateNode (record_arg,first_field_arg,
node->node_state.state_record_arguments,record_a_size,record_b_size,asp_p,bsp_p);
}
}
static LabDef selector_m_error_lab = {NULL,"",False,"selector_m_error",0};
void FillMatchNode (Node node,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
int symbol_arity_eq_one;
Symbol symbol;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
symbol=node->node_symbol;
if (symbol->symb_kind==definition && symbol->symb_def->sdef_kind==CONSTRUCTOR && symbol->symb_def->sdef_arity==1)
symbol_arity_eq_one=1;
else
symbol_arity_eq_one=0;
if (IsSimpleState (node->node_state) && !(symbol_arity_eq_one && !IsLazyState (node->node_state))){
int n_arguments,strict_constructor;
LabDef name,codelab;
SymbDef new_match_sdef;
strict_constructor=0;
if (symbol->symb_kind==definition && symbol->symb_def->sdef_kind==CONSTRUCTOR){
if (symbol->symb_def->sdef_strict_constructor)
strict_constructor=1;
else
if (symbol->symb_def->sdef_type->type_nr_of_constructors==1){
if (symbol_arity_eq_one){
LabDef sellab, nsellab;
BuildLazyTupleSelectorLabel (&nsellab,1,1);
sellab = nsellab;
sellab.lab_pref = d_pref;
if (update_node_id==NULL){
GenBuild (&sellab,-1,&nsellab);
} else {
GenFill (&sellab,-1,&nsellab,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=1;
}
} else
if (update_node_id!=NULL){
GenFillFromA (0,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
GenPopA (1);
*asp_p-=1;
}
return;
}
}
if (!symbol_arity_eq_one)
new_match_sdef=create_match_function (symbol,node->node_arity,strict_constructor);
else
new_match_sdef=create_select_and_match_function (symbol,strict_constructor);
ConvertSymbolToDandNLabel (&name,&codelab,new_match_sdef);
n_arguments=1;
if (update_node_id==NULL){
GenBuild (&name,n_arguments,&codelab);
} else {
GenFill (&name,n_arguments,&codelab,*asp_p-update_node_id->nid_a_index,node->node_state.state_kind==SemiStrict ? PartialFill : NormalFill);
*asp_p-=1;
}
} else {
struct state *demanded_state_array;
int demanded_state_arity;
int a_size,b_size;
struct arg *argument;
struct symbol *symbol;
int branch;
argument = node->node_arguments;
DetermineSizeOfState (argument->arg_state,&a_size,&b_size);
if (CoerceStateKind (StrictOnA,argument->arg_state.state_kind)==Reduce)
GenJsrEval (0);
symbol=node->node_symbol;
branch=1;
switch (symbol->symb_kind){
case cons_symb:
GenEqDesc (&cons_lab,2,0);
break;
case definition:
{
SymbDef sdef;
sdef=symbol->symb_def;
if (sdef->sdef_kind==CONSTRUCTOR){
if (sdef->sdef_type->type_nr_of_constructors==1){
branch=0;
} else {
LabDef symbol_label;
if (sdef->sdef_strict_constructor){
ConvertSymbolToKLabel (&symbol_label,sdef);
GenEqDesc (&symbol_label,0,0);
} else {
ConvertSymbolToConstructorDLabel (&symbol_label,sdef);
GenEqDesc (&symbol_label,node->node_arity,0);
}
}
break;
}
}
default:
error_in_function ("FillMatchNode");
}
if (branch){
#if 1
GenExitFalse (&selector_m_error_lab);
#else
LabDef local_label;
MakeLabel (&local_label,m_symb,NewLabelNr++,no_pref);
GenJmpTrue (&local_label);
GenJmp (&selector_m_error_lab);
GenLabelDefinition (&local_label);
#endif
}
if (symbol_arity_eq_one){
demanded_state_array=&node->node_state;
demanded_state_arity=1;
} else {
demanded_state_array=node->node_state.state_tuple_arguments;
demanded_state_arity=node->node_state.state_arity;
}
if (symbol->symb_kind==definition && symbol->symb_def->sdef_kind==CONSTRUCTOR && symbol->symb_def->sdef_strict_constructor){
StateP constructor_args_state_p;
int a_size,b_size,arity;
arity=symbol->symb_def->sdef_arity;
constructor_args_state_p=symbol->symb_def->sdef_constructor->cl_state_p;
DetermineSizeOfStates (arity,constructor_args_state_p,&a_size,&b_size);
GenReplRArgs (a_size,b_size);
*asp_p -= 1-a_size;
*bsp_p += b_size;
AdjustTuple (a_size,b_size,asp_p,bsp_p,arity,demanded_state_array,constructor_args_state_p,a_size,b_size);
} else {
*asp_p-=1;
UnpackTuple (*asp_p,asp_p,bsp_p,True,demanded_state_arity,demanded_state_array);
}
}
}
#ifdef REUSE_UNIQUE_NODES
# if GENERATE_CODE_AGAIN
extern int call_code_generator_again;
static void restore_removed_arguments (ArgP *arg_h,ArgP removed_args,unsigned int argument_overwrite_bits,int node_arity)
{
int arg_n;
ArgP not_removed_args;
not_removed_args=*arg_h;
for (arg_n=0; arg_n<node_arity; ++arg_n){
if (argument_overwrite_bits & (1<<arg_n)){
*arg_h=not_removed_args;
arg_h=¬_removed_args->arg_next;
not_removed_args=not_removed_args->arg_next;
} else {
*arg_h=removed_args;
arg_h=&removed_args->arg_next;
removed_args=removed_args->arg_next;
}
}
}
# endif
static
#if GENERATE_CODE_AGAIN
ArgP
#else
void
#endif
compute_bits_and_remove_unused_arguments (NodeP node,char bits[],unsigned int argument_overwrite_bits,
int *a_size_p,int *b_size_p,int *n_a_fill_bits_p,int *n_b_fill_bits_p)
{
unsigned int a_bits,b_bits,a_size,b_size,n,arg_n;
int n_a_fill_bits,n_b_fill_bits,node_arity;
ArgS **arg_l;
#if GENERATE_CODE_AGAIN
ArgP removed_args,*removed_args_l;
removed_args_l=&removed_args;
#endif
arg_l=&node->node_arguments;
node_arity=node->node_arity;
a_bits=0;
b_bits=0;
a_size=0;
b_size=0;
n_a_fill_bits=0;
n_b_fill_bits=0;
for (arg_n=0; arg_n<node_arity; ++arg_n){
ArgP arg_p;
int arg_a_size,arg_b_size;
arg_p=*arg_l;
DetermineSizeOfState (arg_p->arg_state,&arg_a_size,&arg_b_size);
if (argument_overwrite_bits & (1<<arg_n)){
a_bits |= (~((~0)<<arg_a_size))<<a_size;
b_bits |= (~((~0)<<arg_b_size))<<b_size;
n_a_fill_bits+=arg_a_size;
n_b_fill_bits+=arg_b_size;
arg_l=&arg_p->arg_next;
} else {
*arg_l=arg_p->arg_next;
#if GENERATE_CODE_AGAIN
*removed_args_l=arg_p;
removed_args_l=&arg_p->arg_next;
#endif
}
a_size+=arg_a_size;
b_size+=arg_b_size;
}
#if GENERATE_CODE_AGAIN
*removed_args_l=NULL;
#endif
for (n=0; n<a_size; ++n)
bits[n+1]='0' + ((a_bits>>n) & 1);
for (n=0; n<b_size; ++n)
bits[n+a_size+1]='0' + ((b_bits>>n) & 1);
bits[a_size+b_size+1]='\0';
*a_size_p=a_size;
*b_size_p=b_size;
*n_a_fill_bits_p=n_a_fill_bits;
*n_b_fill_bits_p=n_b_fill_bits;
#if GENERATE_CODE_AGAIN
return removed_args;
#endif
}
static void FillUniqueNodeWithNode (NodeP update_node,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
unsigned int argument_overwrite_bits,n_args,node_arity,arg_n;
char bits[MaxNodeArity+2];
NodeIdP free_unique_node_id;
NodeP node,push_node;
LabDef name,*label_p;
SymbolP symbol;
ArgS **arg_l;
node=update_node->node_arguments->arg_node;
push_node=update_node->node_node;
free_unique_node_id=push_node->node_arguments->arg_node->node_node_id;
symbol=node->node_symbol;
switch (symbol->symb_kind){
case definition:
{
SymbDef sdef;
sdef=node->node_symbol->symb_def;
node_arity=node->node_arity;
switch (sdef->sdef_kind){
case CONSTRUCTOR:
if (push_node->node_record_symbol==node->node_symbol && push_node->node_arity==node_arity)
bits[0]='0';
else
bits[0]='1';
if (sdef->sdef_strict_constructor){
int a_size,b_size,n_a_fill_bits,n_b_fill_bits;
#if GENERATE_CODE_AGAIN
ArgP removed_args=
#endif
compute_bits_and_remove_unused_arguments (node,bits,update_node->node_arguments->arg_occurrence,
&a_size,&b_size,&n_a_fill_bits,&n_b_fill_bits);
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
#if GENERATE_CODE_AGAIN
if (call_code_generator_again)
restore_removed_arguments (&node->node_arguments,removed_args,update_node->node_arguments->arg_occurrence,node->node_arity);
#endif
ConvertSymbolToKLabel (&name,sdef);
if (a_size+b_size>2)
GenFill2R (&name,a_size,b_size,*asp_p-free_unique_node_id->nid_a_index,bits);
else
GenFill1R (&name,a_size,b_size,*asp_p-free_unique_node_id->nid_a_index,bits);
*asp_p-=n_a_fill_bits;
*bsp_p-=n_b_fill_bits;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
return;
} else {
ConvertSymbolToConstructorDLabel (&name,sdef);
label_p=&name;
}
break;
case RECORDTYPE:
{
int a_size,b_size,n_a_fill_bits,n_b_fill_bits;
#if GENERATE_CODE_AGAIN
ArgP removed_args;
#endif
if (push_node->node_record_symbol==node->node_symbol && push_node->node_arity==node_arity)
bits[0]='0';
else
bits[0]='1';
#if GENERATE_CODE_AGAIN
removed_args=
#endif
compute_bits_and_remove_unused_arguments (node,bits,update_node->node_arguments->arg_occurrence,
&a_size,&b_size,&n_a_fill_bits,&n_b_fill_bits);
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
#if GENERATE_CODE_AGAIN
if (call_code_generator_again)
restore_removed_arguments (&node->node_arguments,removed_args,update_node->node_arguments->arg_occurrence,node->node_arity);
#endif
ConvertSymbolToRLabel (&name,sdef);
if (a_size+b_size>2)
GenFill2R (&name,a_size,b_size,*asp_p-free_unique_node_id->nid_a_index,bits);
else
GenFill1R (&name,a_size,b_size,*asp_p-free_unique_node_id->nid_a_index,bits);
*asp_p-=n_a_fill_bits;
*bsp_p-=n_b_fill_bits;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
return;
}
case IMPRULE:
case DEFRULE:
case SYSRULE:
if (IsLazyState (node->node_state)){
LabDef codelab;
ConvertSymbolToDandNLabel (&name,&codelab,sdef);
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (sdef->sdef_kind==IMPRULE && (sdef->sdef_rule->rule_mark & RULE_UNBOXED_LAZY_CALL)){
int a_size,b_size;
DetermineSizeOfArguments (node->node_arguments,&a_size,&b_size);
if (a_size+b_size>node->node_arity){
*asp_p += 1-a_size;
*bsp_p -= b_size;
if (b_size!=0)
GenBuildU (&name,a_size,b_size,&codelab);
else
GenBuild (&name,a_size,&codelab);
} else {
if (b_size!=0){
GenFillU (&name,a_size,b_size,&codelab,*asp_p-free_unique_node_id->nid_a_index);
*bsp_p -= b_size;
} else
GenFill (&name,a_size,&codelab,*asp_p-free_unique_node_id->nid_a_index,NormalFill);
*asp_p-=a_size;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
}
} else {
GenFill (&name,node->node_arity,&codelab,*asp_p-free_unique_node_id->nid_a_index,NormalFill);
*asp_p-=node->node_arity;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
}
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
return;
} else {
int a_size,b_size;
ConvertSymbolToLabel (&name,sdef);
BuildArgsWithResultNodeOnStack (node->node_arguments,free_unique_node_id,asp_p,bsp_p,code_gen_node_ids_p,&a_size,&b_size);
*asp_p-=a_size;
*bsp_p-=b_size;
if (! (sdef->sdef_kind==SYSRULE
&& sdef->sdef_ident->ident_instructions!=NULL
&& *sdef->sdef_ident->ident_instructions!='\0'
&& *sdef->sdef_ident->ident_instructions!='.'))
{
cleanup_stack (asp_p,bsp_p,a_size,b_size,&code_gen_node_ids_p->a_node_ids,&code_gen_node_ids_p->b_node_ids,
&code_gen_node_ids_p->free_node_ids,code_gen_node_ids_p->moved_node_ids_l,
code_gen_node_ids_p->doesnt_fail);
}
CallFunction (&name,sdef,True,node);
AddSizeOfState (node->node_state,asp_p,bsp_p);
return;
}
default:
error_in_function ("FillUniqueNodeWithNode");
return;
}
break;
}
case cons_symb:
node_arity=2;
if (push_node->node_record_symbol->symb_kind==cons_symb && push_node->node_arity==node_arity)
bits[0]='0';
else
bits[0]='1';
label_p=&cons_lab;
break;
case tuple_symb:
node_arity=node->node_arity;
if (push_node->node_record_symbol->symb_kind==tuple_symb && push_node->node_arity==node_arity)
bits[0]='0';
else
bits[0]='1';
label_p=&tuple_lab;
break;
default:
error_in_function ("FillUniqueNodeWithNode");
return;
}
arg_l=&node->node_arguments;
argument_overwrite_bits=update_node->node_arguments->arg_occurrence;
n_args=0;
#if GENERATE_CODE_AGAIN
{
ArgP removed_args,*removed_args_l;
removed_args_l=&removed_args;
#endif
for (arg_n=0; arg_n<node_arity; ++arg_n){
ArgP arg_p;
arg_p=*arg_l;
if (argument_overwrite_bits & (1<<arg_n)){
bits[arg_n+1]='1';
arg_l=&(arg_p->arg_next);
++n_args;
} else {
bits[arg_n+1]='0';
*arg_l=arg_p->arg_next;
#if GENERATE_CODE_AGAIN
*removed_args_l=arg_p;
removed_args_l=&arg_p->arg_next;
#endif
}
}
#if GENERATE_CODE_AGAIN
*removed_args_l=NULL;
#endif
bits[arg_n+1]='\0';
BuildLazyArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
#if GENERATE_CODE_AGAIN
if (call_code_generator_again)
restore_removed_arguments (&node->node_arguments,removed_args,update_node->node_arguments->arg_occurrence,node_arity);
}
#endif
if (node_arity<=2)
GenFill1 (label_p,node_arity,*asp_p-free_unique_node_id->nid_a_index,bits);
else
GenFill2 (label_p,node_arity,*asp_p-free_unique_node_id->nid_a_index,bits);
*asp_p-=n_args;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
*asp_p+=1;
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
}
#endif
#if ! OPTIMIZE_LAZY_TUPLE_RECURSION
static
#endif
void FillNodeOnACycle (Node node,int *asp_p,int *bsp_p,NodeId update_node_id,CodeGenNodeIdsP code_gen_node_ids_p)
{
switch (node->node_kind){
case NormalNode:
FillNormalNode (node,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
break;
case SelectorNode:
FillOrReduceFieldSelection (node,node->node_symbol->symb_def,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
break;
case UpdateNode:
FillUpdateNode (node,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
break;
case MatchNode:
FillMatchNode (node,asp_p,bsp_p,update_node_id,code_gen_node_ids_p);
break;
default:
error_in_function ("FillNodeOnACycle");
}
}
void Build (Node node,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
switch (node->node_kind){
case NormalNode:
FillNormalNode (node,asp_p,bsp_p,NULL,code_gen_node_ids_p);
break;
case SelectorNode:
FillOrReduceFieldSelection (node,node->node_symbol->symb_def,asp_p,bsp_p,NULL,code_gen_node_ids_p);
break;
case UpdateNode:
FillUpdateNode (node,asp_p,bsp_p,NULL,code_gen_node_ids_p);
break;
case MatchNode:
FillMatchNode (node,asp_p,bsp_p,NULL,code_gen_node_ids_p);
break;
#ifdef REUSE_UNIQUE_NODES
case FillUniqueNode:
FillUniqueNodeWithNode (node,asp_p,bsp_p,code_gen_node_ids_p);
break;
#endif
default:
error_in_function ("Build");
}
}
void build_and_cleanup (Node node,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
SymbDef sdef;
sdef=NULL;
if (node->node_kind==NormalNode){
switch (node->node_symbol->symb_kind){
case definition:
sdef=node->node_symbol->symb_def;
break;
case apply_symb:
sdef=ApplyDef;
break;
#ifndef FASTER_STRICT_IF
case if_symb:
sdef=IfDef;
break;
#endif
}
}
if (sdef!=NULL){
int sdef_kind;
sdef_kind=sdef->sdef_kind;
if ((sdef_kind==IMPRULE || sdef_kind==DEFRULE || sdef_kind==SYSRULE) &&
sdef->sdef_arity==node->node_arity && !IsLazyState (node->node_state))
{
LabDef name;
int a_size,b_size;
ArgP node_args;
ConvertSymbolToLabel (&name,sdef);
node_args=node->node_arguments;
DetermineSizeOfArguments (node_args,&a_size,&b_size);
#if 1
if (ExpectsResultNode (node->node_state))
BuildArgsWithNewResultNode (node_args,asp_p,bsp_p,code_gen_node_ids_p,&a_size,&b_size);
else
#else
if (ExpectsResultNode (node->node_state)){
NewEmptyNode (asp_p,-1);
++a_size;
}
#endif
BuildArgs (node_args,asp_p,bsp_p,code_gen_node_ids_p);
*asp_p-=a_size;
*bsp_p-=b_size;
cleanup_stack (asp_p,bsp_p,a_size,b_size,&code_gen_node_ids_p->a_node_ids,&code_gen_node_ids_p->b_node_ids,
&code_gen_node_ids_p->free_node_ids,code_gen_node_ids_p->moved_node_ids_l,
code_gen_node_ids_p->doesnt_fail);
CallFunction (&name,sdef,True,node);
AddSizeOfState (node->node_state,asp_p,bsp_p);
return;
}
}
Build (node,asp_p,bsp_p,code_gen_node_ids_p);
}
void BuildArg (Args arg,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
NodeP node;
int asize,bsize;
ArgComment (arg);
node=arg->arg_node;
if (node->node_kind!=NodeIdNode){
Build (node,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (node->node_state, &asize, &bsize);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,arg->arg_state,node->node_state,asize,bsize);
} else {
NodeId arg_node_id;
arg_node_id=node->node_node_id;
if (CopyNodeIdArgument (arg->arg_state,arg_node_id,asp_p,bsp_p))
ChangeEvalStatusKindToStrictOnA (arg_node_id,code_gen_node_ids_p->saved_nid_state_l);
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
}
static Bool LazyStates (StateS states[],int n_states)
{
int n;
for (n=0; n<n_states; ++n)
if (!IsLazyState (states[n]))
return False;
return True;
}
static Bool PushArgumentLater (StateS demstate,StateS offstate)
{
if (demstate.state_type==SimpleState && demstate.state_kind==Undefined)
return False;
if (offstate.state_type==SimpleState){
Coercions c;
StateKind offkind;
offkind = offstate.state_kind;
if (demstate.state_type==SimpleState){
c = CoerceStateKind (demstate.state_kind, offkind);
if (c==Reduce || c==MayBecomeCyclicSpine || c==CyclicSpine)
return False;
else
return True;
} else {
c = CoerceStateKind (StrictOnA, offkind);
if (c==Reduce || c==MayBecomeCyclicSpine || c==CyclicSpine)
return False;
switch (demstate.state_type){
case TupleState:
return LazyStates (demstate.state_tuple_arguments,demstate.state_arity);
case RecordState:
return LazyStates (demstate.state_record_arguments,demstate.state_arity);
case ArrayState:
return True;
}
}
} else if (demstate.state_type==SimpleState){
switch (offstate.state_type){
case TupleState:
/*
BuildTuple (aindex,bindex,*asp_p,*bsp_p,offstate.state_arity,offstate.state_tuple_arguments,
offasize,offbsize,*asp_p,NormalFill,newnode);
*/
return False;
case RecordState:
/*
BuildRecord (offstate.state_record_symbol,aindex,bindex,*asp_p,*bsp_p,offasize,offbsize,*asp_p,NormalFill,newnode);
*/
return False;
case ArrayState:
return True;
}
} else {
if (offstate.state_type!=demstate.state_type)
return False;
switch (offstate.state_type){
case TupleState:
{
int n,n_states;
n_states=demstate.state_arity;
for (n=0; n<n_states; ++n)
if (!PushArgumentLater (demstate.state_tuple_arguments[n],offstate.state_tuple_arguments[n]))
return False;
}
return True;
case RecordState:
{
int n,n_states;
n_states=demstate.state_arity;
for (n=0; n<n_states; ++n)
if (!PushArgumentLater (demstate.state_record_arguments[n],offstate.state_record_arguments[n]))
return False;
}
return True;
case ArrayState:
return True;
}
}
return False;
}
static Bool BuildNonParArgs (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
Bool parallel;
if (args==NULL)
return False;
parallel = BuildNonParArgs (args->arg_next,asp_p,bsp_p,code_gen_node_ids_p);
if (args->arg_state.state_mark & STATE_PARALLEL_MASK)
return True;
{
Node node;
int asize,bsize;
node=args->arg_node;
if (node->node_kind!=NodeIdNode){
if (node->node_kind==NormalNode){
switch (node->node_symbol->symb_kind){
case int_denot:
case bool_denot:
case char_denot:
case real_denot:
case string_denot:
args->arg_state.state_mark |= STATE_PARALLEL_MASK;
return True;
}
}
ArgComment (args);
Build (node,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (node->node_state, &asize, &bsize);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,args->arg_state, node->node_state, asize, bsize);
} else {
NodeId arg_node_id;
arg_node_id=node->node_node_id;
if (PushArgumentLater (args->arg_state,arg_node_id->nid_state)){
args->arg_state.state_mark |= STATE_PARALLEL_MASK;
return True;
} else {
ArgComment (args);
if (CopyNodeIdArgument (args->arg_state,arg_node_id,asp_p,bsp_p))
ChangeEvalStatusKindToStrictOnA (arg_node_id,code_gen_node_ids_p->saved_nid_state_l);
decrement_reference_count_of_node_id (arg_node_id,&code_gen_node_ids_p->free_node_ids);
}
}
}
return parallel;
}
#if 0
static void PutArgInFrames (int *anext,int *bnext,int asp,int bsp,StateS state,int asize,int bsize)
{
if (IsSimpleState (state)){
if (state.state_kind == OnB)
PutInBFrames (bsp, bnext, bsize);
else if (state.state_kind != Undefined)
PutInAFrames (asp, anext);
} else {
int i, arity;
arity = state.state_arity;
switch (state.state_type){
case TupleState:
{ States argstates = state.state_tuple_arguments;
asp -= asize;
bsp -= bsize;
for (i=arity-1; i>=0; i--){
DetermineSizeOfState (argstates [i],&asize, &bsize);
asp += asize;
bsp += bsize;
PutArgInFrames (anext, bnext, asp, bsp, argstates [i], asize, bsize);
}
break;
}
case RecordState:
{ States argstates = state.state_record_arguments;
asp -= asize;
bsp -= bsize;
for (i=arity-1; i>=0; i--){
DetermineSizeOfState (argstates [i],&asize, &bsize);
asp += asize;
bsp += bsize;
PutArgInFrames (anext, bnext, asp, bsp, argstates [i], asize, bsize);
}
break;
}
case ArrayState:
PutInAFrames (asp, anext);
break;
}
}
}
#endif
static void PutParAndNormalArgsInFrames (Args args,int *npar_a_offset_p,int *npar_b_offset_p,int *par_a_offset_p,int *par_b_offset_p,int *aind_p,int *bind_p)
{
if (args!=NULL){
int asize,bsize;
PutParAndNormalArgsInFrames (args->arg_next,npar_a_offset_p,npar_b_offset_p,par_a_offset_p,par_b_offset_p,aind_p,bind_p);
DetermineSizeOfState (args->arg_state,&asize,&bsize);
if (args->arg_state.state_mark & STATE_PARALLEL_MASK){
if (bsize!=0){
*par_b_offset_p+=bsize;
PutInBFrames (*par_b_offset_p,bind_p,bsize);
}
while (asize!=0){
++*par_a_offset_p;
PutInAFrames (*par_a_offset_p,aind_p);
--asize;
}
} else {
if (bsize!=0){
*npar_b_offset_p+=bsize;
PutInBFrames (*npar_b_offset_p,bind_p,bsize);
}
while (asize!=0){
++*npar_a_offset_p;
PutInAFrames (*npar_a_offset_p,aind_p);
--asize;
}
}
}
}
static void ReorderParallelAndNonParallelArgsWithResultNode (Args args,int *asize_p,int *bsize_p)
{
int par_a_size,par_b_size;
int npar_a_size,npar_b_size;
int asize,bsize;
int oldamax,oldbmax;
int aind,bind;
ArgS *arg;
par_a_size=1;
par_b_size=0;
npar_a_size=0;
npar_b_size=0;
for_l (arg,args,arg_next)
if (arg->arg_state.state_mark & STATE_PARALLEL_MASK)
AddSizeOfState (arg->arg_state,&par_a_size,&par_b_size);
else
AddSizeOfState (arg->arg_state,&npar_a_size,&npar_b_size);
asize = par_a_size+npar_a_size;
bsize = par_b_size+npar_b_size;
*asize_p=asize;
*bsize_p=bsize;
if ((par_a_size==0 || npar_a_size==0) && (par_b_size==0 || npar_b_size==0))
return;
InitStackConversions (asize+2,bsize+2,&oldamax,&oldbmax);
aind = 0;
bind = 0;
{
int npar_a_offset,npar_b_offset,par_a_offset,par_b_offset;
npar_a_offset=0;
npar_b_offset=0;
par_a_offset=npar_a_size;
par_b_offset=npar_b_size;
par_a_offset+=1;
PutInAFrames (par_a_offset,&aind);
PutParAndNormalArgsInFrames (args,&npar_a_offset,&npar_b_offset,&par_a_offset,&par_b_offset,&aind,&bind);
}
GenAStackConversions (asize,aind);
GenBStackConversions (bsize,bind);
ExitStackConversions (oldamax,oldbmax);
}
static void ReorderParallelAndNonParallelArgs (Args args)
{
int par_a_size,par_b_size;
int npar_a_size,npar_b_size;
int asize,bsize;
int oldamax,oldbmax;
int aind,bind;
ArgS *arg;
par_a_size=0;
par_b_size=0;
npar_a_size=0;
npar_b_size=0;
for_l (arg,args,arg_next)
if (arg->arg_state.state_mark & STATE_PARALLEL_MASK)
AddSizeOfState (arg->arg_state,&par_a_size,&par_b_size);
else
AddSizeOfState (arg->arg_state,&npar_a_size,&npar_b_size);
if ((par_a_size==0 || npar_a_size==0) && (par_b_size==0 || npar_b_size==0))
return;
asize = par_a_size+npar_a_size;
bsize = par_b_size+npar_b_size;
InitStackConversions (asize+2,bsize+2,&oldamax,&oldbmax);
aind = 0;
bind = 0;
{
int npar_a_offset,npar_b_offset,par_a_offset,par_b_offset;
npar_a_offset=0;
npar_b_offset=0;
par_a_offset=npar_a_size;
par_b_offset=npar_b_size;
PutParAndNormalArgsInFrames (args,&npar_a_offset,&npar_b_offset,&par_a_offset,&par_b_offset,&aind,&bind);
}
GenAStackConversions (asize,aind);
GenBStackConversions (bsize,bind);
ExitStackConversions (oldamax,oldbmax);
}
static void BuildParArgs (ArgS* args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (args==NULL)
return;
BuildParArgs (args->arg_next,asp_p,bsp_p,code_gen_node_ids_p);
if (args->arg_state.state_mark & STATE_PARALLEL_MASK){
/* ParComment (args); */
BuildArg (args,asp_p,bsp_p,code_gen_node_ids_p);
}
}
void BuildArgs (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (BuildNonParArgs (args,asp_p,bsp_p,code_gen_node_ids_p)){
BuildParArgs (args,asp_p,bsp_p,code_gen_node_ids_p);
ReorderParallelAndNonParallelArgs (args);
}
}
static void BuildLazyArgs (Args args,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (args==NULL)
return;
BuildLazyArgs (args->arg_next,asp_p,bsp_p,code_gen_node_ids_p);
BuildArg (args,asp_p,bsp_p,code_gen_node_ids_p);
}
static void CreateCyclicExternalReducers (NodeDefs nds,int node_id_number,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
for (; nds && nds->def_id->nid_number==node_id_number; nds=nds->def_next){
if (nds->def_node && (nds->def_id->nid_mark & ON_A_CYCLE_MASK) && HasExternalAnnot (nds->def_node)){
NewEmptyNode (asp_p,-1);
/* fill cycle and start reducer */
FillNodeOnACycle (nds->def_node,asp_p,bsp_p,nds->def_id,code_gen_node_ids_p);
CreateParallelCode (nds,asp_p,bsp_p,code_gen_node_ids_p);
ChangeEvalStatusKind (nds->def_id,OnA);
}
}
}
#if OPTIMIZE_LAZY_TUPLE_RECURSION
extern NodeP tuple_result_p;
static void generate_code_for_lazy_tuple_recursive_call (NodeP node,NodeIdP node_id_p,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
unsigned long result_and_call_same_select_vector;
NodeIdP first_tuple_call_node_id_p;
int n,arity,tuple_arity;
LabDef name,codelab;
NodeP fill_nodes;
SymbDef sdef;
fill_nodes=node;
while (node->node_kind==FillUniqueNode)
node=node->node_arguments->arg_node;
result_and_call_same_select_vector=0;
first_tuple_call_node_id_p=NULL;
if (lazy_tuple_recursion){
ArgP tuple_element_p;
for_li (tuple_element_p,n,tuple_result_p->node_arguments,arg_next){
NodeP node_p;
node_p=tuple_element_p->arg_node;
if (node_p->node_symbol->symb_kind==select_symb
&& node_p->node_arguments->arg_node->node_kind==NodeIdNode
&& n+1==node_p->node_arity
&& (node_p->node_arguments->arg_node->node_node_id->nid_mark2 & NID_CALL_VIA_LAZY_SELECTIONS_ONLY)
){
NodeIdP tuple_call_node_id_p;
tuple_call_node_id_p=node_p->node_arguments->arg_node->node_node_id;
if (first_tuple_call_node_id_p==NULL)
first_tuple_call_node_id_p=tuple_call_node_id_p;
if (tuple_call_node_id_p==node_id_p)
result_and_call_same_select_vector |= (1<<n);
}
}
}
tuple_arity=node->node_symbol->symb_def->sdef_rule->rule_type->type_alt_rhs->type_node_arity;
if (lazy_tuple_recursion){
for (n=tuple_arity-1; n>=0; --n){
if (result_and_call_same_select_vector & (1<<n))
GenPushA (*asp_p - (tuple_arity-n));
else {
if (fill_nodes!=node){
NodeIdP free_unique_node_id;
free_unique_node_id=fill_nodes->node_node->node_arguments->arg_node->node_node_id;
GenPushA (*asp_p-free_unique_node_id->nid_a_index);
decrement_reference_count_of_node_id (free_unique_node_id,&code_gen_node_ids_p->free_node_ids);
fill_nodes=fill_nodes->node_arguments->arg_node;
} else
GenCreate (-1);
}
++*asp_p;
}
#if ! SELECTORS_FIRST
{
int offset;
offset=tuple_arity-1;
for (n=tuple_arity-1; n>=0; --n){
if (result_and_call_same_select_vector & (1<<n)){
--offset;
} else {
GenPushA (offset);
++*asp_p;
}
}
}
#endif
} else {
for (n=tuple_arity-1; n>=0; --n){
GenCreate (-1);
++*asp_p;
}
#if ! SELECTORS_FIRST
for (n=tuple_arity-1; n>=0; --n){
GenPushA (tuple_arity-1);
++*asp_p;
}
#endif
}
arity=node->node_arity;
if (node->node_kind!=NormalNode || node->node_symbol->symb_kind!=definition || node->node_symbol->symb_def->sdef_kind!=IMPRULE
|| arity!=node->node_symbol->symb_def->sdef_arity || !IsLazyState (node->node_state))
error_in_function ("generate_code_for_lazy_tuple_recursive_call");
sdef=node->node_symbol->symb_def;
ConvertSymbolToDandNLabel (&name,&codelab,sdef);
codelab.lab_post=2;
name.lab_post=2;
BuildArgs (node->node_arguments,asp_p,bsp_p,code_gen_node_ids_p);
if (!lazy_tuple_recursion || first_tuple_call_node_id_p!=node_id_p){
if (node->node_symbol->symb_def->sdef_rule->rule_mark & RULE_UNBOXED_LAZY_CALL){
int a_size,b_size;
DetermineSizeOfArguments (node->node_arguments,&a_size,&b_size);
# if SELECTORS_FIRST
for (n=tuple_arity-1; n>=0; --n){
GenPushA (a_size+tuple_arity-1);
++*asp_p;
}
# endif
if (b_size!=0)
GenBuildU (&name,a_size+tuple_arity,b_size,&codelab);
else
GenBuild (&name,arity+tuple_arity,&codelab);
*bsp_p -= b_size;
*asp_p += 1-(a_size+tuple_arity);
} else {
# if SELECTORS_FIRST
for (n=tuple_arity-1; n>=0; --n){
GenPushA (arity+tuple_arity-1);
++*asp_p;
}
# endif
GenBuild (&name,arity+tuple_arity,&codelab);
*asp_p += 1-(arity+tuple_arity);
}
} else {
char bits[MaxNodeArity+2],*bits_p;
int n,n_updated_tuple_elements;
bits_p=bits;
# if SELECTORS_FIRST
*bits_p++='1';
# else
*bits_p++='0';
# endif
n_updated_tuple_elements=0;
# if SELECTORS_FIRST
for (n=0; n<tuple_arity; ++n)
if (result_and_call_same_select_vector & (1<<n)){
*bits_p++ = '0';
} else {
*bits_p++ = '1';
++n_updated_tuple_elements;
}
# endif
if (node->node_symbol->symb_def->sdef_rule->rule_mark & RULE_UNBOXED_LAZY_CALL){
int a_size,b_size;
DetermineSizeOfArguments (node->node_arguments,&a_size,&b_size);
# if SELECTORS_FIRST
{
int offset;
offset=tuple_arity-1;
for (n=tuple_arity-1; n>=0; --n){
if (result_and_call_same_select_vector & (1<<n)){
--offset;
} else {
GenPushA (a_size+offset);
++*asp_p;
}
}
}
# endif
for (n=0; n<a_size; ++n)
*bits_p++ = '1';
# if !SELECTORS_FIRST
for (n=0; n<tuple_arity; ++n)
if (result_and_call_same_select_vector & (1<<n)){
*bits_p++ = '0';
} else {
*bits_p++ = '1';
++n_updated_tuple_elements;
}
# endif
for (n=0; n<b_size; ++n)
*bits_p++ = '1';
*bits_p++='\0';
if (b_size!=0)
GenFillcpU (&name,a_size+tuple_arity,b_size,&codelab,*asp_p,bits);
else
GenFillcp (&name,a_size+tuple_arity,&codelab,*asp_p,bits);
*asp_p -= a_size+n_updated_tuple_elements;
*bsp_p -= b_size;
} else {
# if SELECTORS_FIRST
{
int offset;
offset=tuple_arity-1;
for (n=tuple_arity-1; n>=0; --n){
if (result_and_call_same_select_vector & (1<<n)){
--offset;
} else {
GenPushA (arity+offset);
++*asp_p;
}
}
}
# endif
for (n=0; n<arity; ++n)
*bits_p++ = '1';
# if !SELECTORS_FIRST
for (n=0; n<tuple_arity; ++n)
if (result_and_call_same_select_vector & (1<<n)){
*bits_p++ = '0';
} else {
*bits_p++ = '1';
++n_updated_tuple_elements;
}
# endif
*bits_p++='\0';
GenFillcp (&name,arity+tuple_arity,&codelab,*asp_p,bits);
*asp_p -= arity+n_updated_tuple_elements;
}
GenPushA (*asp_p);
++*asp_p;
}
{
int offset;
offset=1;
for (n=0; n<tuple_arity; ++n){
if (!lazy_tuple_recursion || !(result_and_call_same_select_vector & (1<<n))){
LabDef sellab,nsellab;
MakeLabel (&nsellab,"_Sel",0,n_pref);
sellab = nsellab;
sellab.lab_pref = d_pref;
GenPushA (0);
GenFill (&sellab,1,&nsellab,offset+1,NormalFill);
}
++offset;
}
}
}
#endif
static int FillNodeDefs (NodeDefs nds,int node_id_number,int *asp_p,int *bsp_p,NodeDefs *rest,CodeGenNodeIdsP code_gen_node_ids_p)
{
int hasCyclicExternalReducer;
hasCyclicExternalReducer=0;
for (; nds!=NULL && nds->def_id->nid_number==node_id_number; nds=nds->def_next){
Node node;
node=nds->def_node;
if (node==NULL){
NodeId node_id;
node_id=nds->def_id;
/* we have a strict annotated left hand side nodeid */
StrictIdComment (node_id);
/* evaluate strict arg */
if (node_id->nid_state.state_type==SimpleState)
ReduceArgumentToHnf (node_id,node_id->nid_state,*asp_p-node_id->nid_a_index,code_gen_node_ids_p->saved_nid_state_l);
} else {
struct state *result_state_p;
result_state_p=&node->node_state;
if (nds->def_id->nid_mark & ON_A_CYCLE_MASK){
if (HasExternalAnnot (node)){
hasCyclicExternalReducer=1;
continue;
}
/* fill cycle */
FillNodeOnACycle (node,asp_p,bsp_p,nds->def_id,code_gen_node_ids_p);
} else {
int a_size,b_size;
NodeDefComment (nds, "shared or annotated");
#if OPTIMIZE_LAZY_TUPLE_RECURSION
if (nds->def_id->nid_mark2 & NID_CALL_VIA_LAZY_SELECTIONS_ONLY)
generate_code_for_lazy_tuple_recursive_call (node,nds->def_id,asp_p,bsp_p,code_gen_node_ids_p);
else
#endif
if (node->node_kind==TupleSelectorsNode){
struct arg *arg;
struct node *tuple_node;
struct state *tuple_state_p;
tuple_node=node->node_node;
if (tuple_node->node_kind!=NodeIdNode){
build_and_cleanup (tuple_node,asp_p,bsp_p,code_gen_node_ids_p);
tuple_state_p=&tuple_node->node_state;
} else {
NodeId node_id;
node_id=tuple_node->node_node_id;
if (CopyNodeIdArgument (tuple_node->node_arguments->arg_state,node_id,asp_p,bsp_p))
ChangeEvalStatusKindToStrictOnA (node_id,code_gen_node_ids_p->saved_nid_state_l);
tuple_state_p=&tuple_node->node_arguments->arg_state;
decrement_reference_count_of_node_id (node_id,&code_gen_node_ids_p->free_node_ids);
}
arg=node->node_arguments;
if (arg->arg_node->node_kind==NodeIdNode){
int a_offset,b_offset,i;
DetermineSizeOfState (*tuple_state_p,&a_offset,&b_offset);
if (tuple_state_p->state_type!=TupleState)
error_in_function ("FillNodeDefs");
for (i=tuple_state_p->state_arity-1; i>=0; --i){
int a_size,b_size;
NodeId node_id;
DetermineSizeOfState (tuple_state_p->state_tuple_arguments[i],&a_size,&b_size);
a_offset-=a_size;
b_offset-=b_size;
if (arg!=NULL && arg->arg_node->node_node_id->nid_number==i){
node_id=arg->arg_node->node_node_id;
arg=arg->arg_next;
} else {
if (a_size==0 && b_size==0)
continue;
node_id=NewNodeId (NULL);
add_node_id_to_list (node_id,&code_gen_node_ids_p->free_node_ids);
}
node_id->nid_a_index_=*asp_p - a_offset;
node_id->nid_b_index_=*bsp_p - b_offset;
node_id->nid_state_ = tuple_state_p->state_tuple_arguments[i];
if (a_size!=0)
add_node_id_to_list (node_id,&code_gen_node_ids_p->a_node_ids);
if (b_size!=0)
add_node_id_to_list (node_id,&code_gen_node_ids_p->b_node_ids);
}
if (arg!=NULL)
error_in_function ("FillNodeDefs");
continue;
}
} else if (node->node_kind==NodeIdNode){
NodeId node_id;
node_id=node->node_node_id;
if ((node_id->nid_mark & NID_SHARED_SELECTION_NODE_ID)==0 && EqualState (node->node_arguments->arg_state,node->node_state)){
int a_size,b_size;
nds->def_id->nid_a_index_=node_id->nid_a_index;
nds->def_id->nid_b_index_=node_id->nid_b_index;
nds->def_id->nid_state_=node_id->nid_state;
DetermineSizeOfState (node_id->nid_state,&a_size,&b_size);
if (a_size!=0){
NodeIdListElementP p_node_id;
for_l (p_node_id,code_gen_node_ids_p->a_node_ids,nidl_next)
if (p_node_id->nidl_node_id==node_id){
p_node_id->nidl_node_id=nds->def_id;
break;
}
}
if (b_size!=0){
NodeIdListElementP p_node_id;
for_l (p_node_id,code_gen_node_ids_p->a_node_ids,nidl_next)
if (p_node_id->nidl_node_id==node_id){
p_node_id->nidl_node_id=nds->def_id;
break;
}
}
continue;
} else {
result_state_p=&node->node_arguments->arg_state;
#ifdef DO_LAZY_SELECTORS_FROM_BOXED_STRICT_RECORDS
if (result_state_p->state_type==SimpleState && result_state_p->state_kind==OnA && !ResultIsNotInRootNormalForm (node_id->nid_state))
result_state_p->state_kind=StrictOnA;
#endif
if (CopyNodeIdArgument (*result_state_p,node_id,asp_p,bsp_p))
ChangeEvalStatusKindToStrictOnA (node_id,code_gen_node_ids_p->saved_nid_state_l);
decrement_reference_count_of_node_id (node_id,&code_gen_node_ids_p->free_node_ids);
}
} else
build_and_cleanup (node,asp_p,bsp_p,code_gen_node_ids_p);
/* IsLazyState (nds->def_node->node_state) ? build shared or annotated : build and reduce */
DetermineSizeOfState (*result_state_p,&a_size,&b_size);
if (a_size!=0)
add_node_id_to_list (nds->def_id,&code_gen_node_ids_p->a_node_ids);
if (b_size!=0)
add_node_id_to_list (nds->def_id,&code_gen_node_ids_p->b_node_ids);
nds->def_id->nid_a_index_=*asp_p;
nds->def_id->nid_b_index_=*bsp_p;
}
/* start reducer, and (if a node is filled) set eval status */
if (IsSimpleState (*result_state_p) && result_state_p->state_kind==Parallel){
if (!((nds->def_id->nid_mark & ON_A_CYCLE_MASK) && HasExternalAnnot (node))){
CreateParallelCode (nds,asp_p,bsp_p,code_gen_node_ids_p);
/* start reducer */
ChangeEvalStatusKind (nds->def_id, OnA);
}
} else
nds->def_id->nid_state_=*result_state_p;
}
}
*rest = nds;
return hasCyclicExternalReducer;
}
Bool NodeOnACycleIsInRootNormalForm (Node node)
{
Symbol symb;
symb=node->node_symbol;
switch (symb->symb_kind){
case select_symb:
case apply_symb:
return False;
case if_symb:
return (node->node_arity!=3);
case definition:
{
SymbDef sdef;
sdef=symb->symb_def;
if (node->node_kind!=NormalNode)
return False;
if (sdef->sdef_kind==RECORDTYPE)
if (!sdef->sdef_strict_constructor)
return True;
else
return False;
if (sdef->sdef_arity==node->node_arity)
switch (sdef->sdef_kind){
case CONSTRUCTOR:
if (sdef->sdef_strict_constructor)
return False;
case DEFRULE:
case SYSRULE:
case IMPRULE:
return False;
default:
return True;
}
return True;
}
default:
return True;
}
}
static void CreateCycleNodesAndChannels (NodeDefs nds,NodeDefs rootdef,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
for (; nds!=NULL; nds=nds->def_next){
if (! nds->def_node || nds==rootdef){
/* we have a strict annotated left hand side nodeid, or a root (with a node) */
continue;
} else if (nds->def_id->nid_mark & ON_A_CYCLE_MASK){
if (HasExternalAnnot (nds->def_node)){
NodeDefComment (nds, "Cycle containing a channel");
GenProcIdCalculation (nds->def_node,nds->def_node->node_annotation,asp_p,bsp_p,code_gen_node_ids_p);
GenCreateChannel (channel_code);
--*bsp_p;
nds->def_id->nid_state_=nds->def_node->node_state;
} else {
NodeDefComment (nds, "OnACycle");
if (NodeOnACycleIsInRootNormalForm (nds->def_node))
GenCreate (-1);
else
GenCreate (nds->def_node->node_arity);
nds->def_id->nid_state_=OnAState;
}
++*asp_p;
nds->def_id->nid_a_index_=*asp_p;
} else
nds->def_id->nid_state_=UnderEvalState;
}
}
void CodeSharedNodeDefs (NodeDefs nds, NodeDefs rootdef,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p)
{
NodeDefs rest,new_rest;
CreateCycleNodesAndChannels (nds, rootdef,asp_p,bsp_p,code_gen_node_ids_p);
for (rest=nds; rest!=NULL; rest=new_rest){
int hasCyclicExternalReducer;
hasCyclicExternalReducer=FillNodeDefs (rest,rest->def_id->nid_number,asp_p,bsp_p,&new_rest,code_gen_node_ids_p);
if (hasCyclicExternalReducer)
CreateCyclicExternalReducers (rest, rest->def_id->nid_number,asp_p,bsp_p,code_gen_node_ids_p);
}
ReduceSemiStrictNodes (nds,*asp_p);
}
#if 0
static void BuildStackFrameEntry (Args arg,int *asp_p,int *bsp_p,int *a_ind,int *b_ind,CodeGenNodeIdsP code_gen_node_ids_p)
{
int asize, bsize;
Node pattern;
pattern=arg->arg_node;
if (pattern->node_kind!=NodeIdNode){
Build (pattern,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (pattern->node_state, &asize, &bsize);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,arg->arg_state,pattern->node_state,asize,bsize);
DetermineSizeOfState (arg->arg_state,&asize,&bsize);
PutArgInFrames (a_ind,b_ind,*asp_p,*bsp_p,arg->arg_state,asize,bsize);
} else {
StateS offstate;
int aindex;
NodeId arg_node_id;
arg_node_id=pattern->node_node_id;
offstate = arg_node_id->nid_state;
aindex = arg_node_id->nid_a_index;
if (IsSimpleState (offstate)){
Bool leftontop;
Coercions c;
c = CoerceSimpleStateArgument (arg->arg_state,offstate.state_kind,aindex,asp_p,False, &leftontop);
offstate.state_kind = AdjustStateKind (offstate.state_kind, c);
if (HasBeenReduced (c))
ChangeEvalStatusKindToStrictOnA (arg_node_id,code_gen_node_ids_p->saved_nid_state_l);
if (leftontop)
aindex = *asp_p;
}
DetermineSizeOfState (offstate, &asize, &bsize);
CoerceArgumentUsingStackFrames (arg->arg_state,offstate,aindex,arg_node_id->nid_b_index,asp_p,bsp_p,a_ind, b_ind, asize, bsize);
}
}
static Bool BuildStackFrameEntries (Args args,int *asp_p,int *bsp_p,int *a_ind,int *b_ind,CodeGenNodeIdsP code_gen_node_ids_p)
{
int parallel;
parallel = False;
if (args){
if (BuildStackFrameEntries (args->arg_next,asp_p,bsp_p, a_ind, b_ind,code_gen_node_ids_p))
parallel = True;
if (args->arg_state.state_parallel)
parallel = True;
else
BuildStackFrameEntry (args,asp_p,bsp_p, a_ind, b_ind,code_gen_node_ids_p);
}
return parallel;
}
static void BuildParallelStackFrameEntries (Args args,int *asp_p,int *bsp_p,int *a_ind,int *b_ind,CodeGenNodeIdsP code_gen_node_ids_p)
{
if (args){
BuildParallelStackFrameEntries (args->arg_next,asp_p,bsp_p, a_ind, b_ind,code_gen_node_ids_p);
if (args->arg_state.state_parallel){
ParComment (args);
BuildStackFrameEntry (args, asp_p,bsp_p, a_ind, b_ind,code_gen_node_ids_p);
}
}
}
static void CopyToNewFrame (int *demframe, int *newdemframe, int size, int *sp1, int *sp2)
{
int i, j, k;
for (i = 0, j = *sp1, k = *sp2; i < size; i++, j--, k--)
newdemframe[k] = demframe[j];
*sp1 -= size;
*sp2 -= size;
}
static void AdjustDemandedFrames (Args args)
{
int *newdemaframe, *newdembframe;
int asp, parasp, newasp, bsp, parbsp, newbsp, asize, bsize, parasize, parbsize;
Args arg;
/* determine sizes of (non) parallel part */
asize = bsize = parasize = parbsize = 0;
for (arg = args; arg; arg = arg->arg_next){
if (arg->arg_state.state_parallel)
AddSizeOfState (arg->arg_state, ¶size, &parbsize);
else
AddSizeOfState (arg->arg_state, &asize, &bsize);
}
if (parasize == 0 && parbsize == 0)
return;
/* allocate space for temporary stack frames */
newdemaframe = AllocTempDemandedAFrame (CurrentAFrameSize);
newdembframe = AllocTempDemandedBFrame (CurrentBFrameSize);
/* copy the arguments to the temporary frames */
parasp = newasp = asize + parasize;
parbsp = newbsp = bsize + parbsize;
asp = asize;
bsp = bsize;
for_l (arg,args,arg_next){
int asize,bsize;
DetermineSizeOfState (arg->arg_state, &asize, &bsize);
if (arg->arg_state.state_parallel){
CopyToNewFrame (DemandedAFrame, newdemaframe, asize, ¶sp, &newasp);
CopyToNewFrame (DemandedBFrame, newdembframe, bsize, &parbsp, &newbsp);
} else {
CopyToNewFrame (DemandedAFrame, newdemaframe, asize, &asp, &newasp);
CopyToNewFrame (DemandedBFrame, newdembframe, bsize, &bsp, &newbsp);
}
}
/* copy the new frame */
for (asp = 1; asp <= asize + parasize; asp++)
DemandedAFrame[asp] = newdemaframe[asp];
for (bsp = 1; bsp <= bsize + parbsize; bsp++)
DemandedBFrame[bsp] = newdembframe[bsp];
}
static void BuildNewStackFrame (ArgS *args,int asp,int bsp,Bool result_node_necessary,CodeGenNodeIdsP code_gen_node_ids_p)
{
int a_ind, b_ind, oldamax, oldbmax, newamax, newbmax, dummy;
Args arg;
a_ind = 0;
b_ind = 0;
dummy=0;
newamax = asp + 2;
newbmax = bsp + 2;
for_l (arg,args,arg_next)
AddStateSizeAndMaxFrameSize (arg->arg_state,& newamax, & dummy, & newbmax);
InitStackConversions (newamax, newbmax, &oldamax, &oldbmax);
if (result_node_necessary){
NewEmptyNode (&asp, -1);
PutInAFrames (asp, &a_ind);
}
TypeErrorFound = False;
CycleErrorFound = False;
if (BuildStackFrameEntries (args, &asp, &bsp,&a_ind, &b_ind,code_gen_node_ids_p)){
BuildParallelStackFrameEntries (args, &asp, &bsp,&a_ind, &b_ind,code_gen_node_ids_p);
AdjustDemandedFrames (args);
}
if (! (TypeErrorFound || CycleErrorFound)){
GenAStackConversions (asp,a_ind);
GenBStackConversions (bsp,b_ind);
}
ExitStackConversions (oldamax, oldbmax);
}
#endif
static void move_a_stack_pointer (int old_asp,int new_asp)
{
if (old_asp<new_asp){
int offset;
offset=0;
GenBuildh (&nil_lab,0);
++old_asp;
while (old_asp<new_asp){
GenPushA (offset);
++offset;
++old_asp;
}
} else
GenPopA (old_asp-new_asp);
}
void UpdateStackPointers (int old_asp,int old_bsp,int new_asp,int new_bsp)
{
move_a_stack_pointer (old_asp,new_asp);
if (old_bsp<new_bsp){
int offset;
SymbValue sv;
offset=0;
sv.val_int="0";
PushBasic (IntObj,sv);
++old_bsp;
while (old_bsp<new_bsp){
GenPushB (offset);
++offset;
++old_bsp;
}
} else
GenPopB (old_bsp-new_bsp);
}
static void AdjustStacksAndJumpToThenOrElseLabel
(Label truelab,Label falselab,Label next_label,int asp,int bsp,int bsize,int then_asp,int then_bsp,int else_asp,int else_bsp)
{
if (then_asp==else_asp){
move_a_stack_pointer (asp,then_asp);
then_asp = else_asp = asp;
}
if (then_bsp==else_bsp){
if (bsp-bsize<then_bsp){
int offset,n;
SymbValue sv;
offset=0;
sv.val_int="0";
PushBasic (IntObj,sv);
++bsp;
while (bsp-bsize<then_bsp){
GenPushB (offset);
++offset;
++bsp;
}
++offset;
for (n=0; n<bsize; ++n)
GenUpdateB (n+offset,n);
} else {
UpdateBasic (bsize,bsize-1,bsp-then_bsp-bsize);
GenPopB (bsp-then_bsp-bsize);
}
then_bsp = else_bsp = bsp - bsize;
}
if (asp==else_asp && bsp - else_bsp - bsize == 0){
#if 1
if (falselab==next_label && asp==then_asp && bsp-bsize==then_bsp){
GenJmpTrue (truelab);
truelab->lab_mod=NULL;
} else
#endif
{
GenJmpFalse (falselab);
falselab->lab_mod=NULL;
UpdateStackPointers (asp, bsp-bsize, then_asp, then_bsp);
#if 1
if (truelab!=next_label)
#endif
{
GenJmp (truelab);
truelab->lab_mod=NULL;
}
}
} else if (asp==then_asp && bsp - then_bsp - bsize == 0){
#if 1
if (truelab==next_label && asp==else_asp && bsp-bsize==else_bsp){
GenJmpTrue (falselab);
falselab->lab_mod=NULL;
} else
#endif
{
GenJmpTrue (truelab);
truelab->lab_mod=NULL;
UpdateStackPointers (asp, bsp-bsize, else_asp, else_bsp);
#if 1
if (falselab!=next_label)
#endif
{
GenJmp (falselab);
falselab->lab_mod=NULL;
}
}
} else {
LabDef loclab;
MakeLabel (&loclab, m_symb, NewLabelNr++, no_pref);
GenJmpFalse (&loclab);
UpdateStackPointers (asp, bsp-bsize, then_asp, then_bsp);
GenJmp (truelab);
truelab->lab_mod=NULL;
GenLabelDefinition (&loclab);
UpdateStackPointers (asp, bsp-bsize, else_asp, else_bsp);
#if 1
if (falselab!=next_label)
#endif
{
GenJmp (falselab);
falselab->lab_mod=NULL;
}
}
}
void EvaluateCondition (Node cond_node,int *asp_p,int *bsp_p,CodeGenNodeIdsP code_gen_node_ids_p,StateS resultstate)
{
switch (cond_node->node_kind){
case NodeIdNode:
{
NodeId nid;
int boolean_b_size;
nid=cond_node->node_node_id;
CopyNodeIdArgument (resultstate,nid,asp_p,bsp_p);
decrement_reference_count_of_node_id (nid,&code_gen_node_ids_p->free_node_ids);
boolean_b_size = ObjectSizes [resultstate.state_object];
*bsp_p-=boolean_b_size;
break;
}
case NormalNode:
case SelectorNode:
case MatchNode:
{
int asize,bsize,boolean_b_size;
Build (cond_node,asp_p,bsp_p,code_gen_node_ids_p);
DetermineSizeOfState (cond_node->node_state,&asize,&bsize);
CoerceArgumentOnTopOfStack (asp_p,bsp_p,resultstate,cond_node->node_state,asize,bsize);
boolean_b_size = ObjectSizes [resultstate.state_object];
*bsp_p-=boolean_b_size;
break;
}
case IfNode:
EvaluateCondition (cond_node->node_arguments->arg_node,asp_p,bsp_p,code_gen_node_ids_p,resultstate);
break;
default:
error_in_function ("EvaluateCondition");
}
}
static Bool IsBooleanValue (Node node, Bool *val)
{
if (node->node_kind==NormalNode && node->node_symbol->symb_kind==bool_denot){
*val = node->node_symbol->symb_bool;
return True;
} else
return False;
}
void subtract_else_ref_counts (struct node_id_ref_count_list *else_node_id_ref_counts,NodeIdListElementS **free_node_ids_l)
{
struct node_id_ref_count_list *else_node_id_ref_count;
for_l (else_node_id_ref_count,else_node_id_ref_counts,nrcl_next){
struct node_id *node_id;
int ref_count;
node_id=else_node_id_ref_count->nrcl_node_id;
ref_count=node_id->nid_refcount;
if (ref_count>=0){
ref_count -= else_node_id_ref_count->nrcl_ref_count;
node_id->nid_refcount=ref_count;
if (ref_count==0)
add_node_id_to_list (node_id,free_node_ids_l);
} else {
ref_count += else_node_id_ref_count->nrcl_ref_count;
node_id->nid_refcount=ref_count;
if (ref_count==-1){
if (! (node_id->nid_node!=NULL && !IsSimpleState (node_id->nid_state)) && unused_node_id_(node_id))
add_node_id_to_list (node_id,free_node_ids_l);
}
}
}
}
void add_else_ref_counts (struct node_id_ref_count_list *else_node_id_ref_counts)
{
struct node_id_ref_count_list *else_node_id_ref_count;
for_l (else_node_id_ref_count,else_node_id_ref_counts,nrcl_next){
struct node_id *node_id;
node_id=else_node_id_ref_count->nrcl_node_id;
if (node_id->nid_refcount>=0)
node_id->nid_refcount += else_node_id_ref_count->nrcl_ref_count;
else
node_id->nid_refcount -= else_node_id_ref_count->nrcl_ref_count;
}
}
static void EvaluateThenOrElsePartOfCondition
(NodeDefs defs,Node node,int asp,int bsp,StateS resultstate, Label truelab, Label falselab,Label next_label,
int then_asp,int then_bsp,int else_asp,int else_bsp,NodeIdListElementP a_node_ids,NodeIdListElementP b_node_ids,
struct node_id_ref_count_list *else_node_id_ref_counts,NodeIdListElementP free_node_ids);
void BranchOnCondition (Node condnode,int asp,int bsp,CodeGenNodeIdsP code_gen_node_ids_p, StateS resultstate,
Label truelab,Label falselab,Label next_label,int then_asp,int then_bsp,int else_asp,int else_bsp)
{
switch (condnode->node_kind){
case NodeIdNode:
case NormalNode:
case SelectorNode:
case MatchNode:
{
int boolean_b_size;
boolean_b_size = ObjectSizes [resultstate.state_object];
AdjustStacksAndJumpToThenOrElseLabel (truelab,falselab,next_label,asp,bsp+boolean_b_size,boolean_b_size,then_asp,then_bsp,else_asp,else_bsp);
break;
}
case IfNode:
{
Bool bool;
Label thenlabel,elselabel;
LabDef thenlab,elselab;
int new_then_asp,new_then_bsp,new_else_asp,new_else_bsp;
Args condpart;
new_then_asp = asp;
new_then_bsp = bsp,
new_else_asp = asp;
new_else_bsp = bsp;
condpart = condnode->node_arguments;
if (IsBooleanValue (condpart->arg_next->arg_node,&bool)){
if (bool){
thenlabel = truelab;
new_then_asp = then_asp;
new_then_bsp = then_bsp;
} else {
thenlabel = falselab;
new_then_asp = else_asp;
new_then_bsp = else_bsp;
}
} else {
thenlabel = NULL;
MakeLabel (&thenlab, then_symb, NewLabelNr++, no_pref);
thenlab.lab_mod=notused_string;
}
if (IsBooleanValue (condpart->arg_next->arg_next->arg_node,&bool)){
if (bool){
elselabel = truelab;
new_else_asp = then_asp;
new_else_bsp = then_bsp;
} else {
elselabel = falselab;
new_else_asp = else_asp;
new_else_bsp = else_bsp;
}
} else {
elselabel = NULL;
MakeLabel (&elselab, else_symb, NewLabelNr++, no_pref);
elselab.lab_mod=notused_string;
}
BranchOnCondition (condpart->arg_node,asp,bsp,code_gen_node_ids_p,resultstate,
thenlabel ? thenlabel : &thenlab, elselabel ? elselabel : &elselab,
!thenlabel ? &thenlab : !elselabel ? &elselab : next_label,
new_then_asp, new_then_bsp, new_else_asp, new_else_bsp);
if (!thenlabel){
if (thenlab.lab_mod==NULL)
GenLabelDefinition (&thenlab);
EvaluateThenOrElsePartOfCondition (condnode->node_then_node_defs,
condpart->arg_next->arg_node, asp,bsp,resultstate,truelab,falselab,!elselabel ? &elselab : next_label,
then_asp,then_bsp,else_asp,else_bsp,code_gen_node_ids_p->a_node_ids,code_gen_node_ids_p->b_node_ids,
condnode->node_else_node_id_ref_counts,code_gen_node_ids_p->free_node_ids);
}
if (!elselabel){
if (elselab.lab_mod==NULL)
GenLabelDefinition (&elselab);
EvaluateThenOrElsePartOfCondition (condnode->node_else_node_defs,
condpart->arg_next->arg_next->arg_node,asp,bsp,resultstate,truelab,falselab,next_label,
then_asp,then_bsp,else_asp,else_bsp,code_gen_node_ids_p->a_node_ids,code_gen_node_ids_p->b_node_ids,
NULL,code_gen_node_ids_p->free_node_ids);
}
break;
}
default:
error_in_function ("BranchOnCondition");
}
}
static void EvaluateThenOrElsePartOfCondition
(NodeDefs defs,Node node,int asp,int bsp,StateS resultstate, Label truelab, Label falselab,Label next_label,
int then_asp,int then_bsp,int else_asp,int else_bsp,NodeIdListElementP a_node_ids,NodeIdListElementP b_node_ids,
struct node_id_ref_count_list *else_node_id_ref_counts,NodeIdListElementP free_node_ids)
{
SavedNidStateP saved_node_id_states;
MovedNodeIdP moved_node_ids;
struct code_gen_node_ids code_gen_node_ids;
saved_node_id_states=NULL;
moved_node_ids=NULL;
if (else_node_id_ref_counts!=NULL)
subtract_else_ref_counts (else_node_id_ref_counts,&free_node_ids);
code_gen_node_ids.free_node_ids=free_node_ids;
code_gen_node_ids.saved_nid_state_l=&saved_node_id_states;
code_gen_node_ids.doesnt_fail=False;
code_gen_node_ids.moved_node_ids_l=&moved_node_ids;
code_gen_node_ids.a_node_ids=a_node_ids;
code_gen_node_ids.b_node_ids=b_node_ids;
CodeSharedNodeDefs (defs,NULL,&asp,&bsp,&code_gen_node_ids);
EvaluateCondition (node,&asp,&bsp,&code_gen_node_ids,resultstate);
BranchOnCondition (node,asp,bsp,&code_gen_node_ids,resultstate,truelab,falselab,next_label,then_asp,then_bsp,else_asp,else_bsp);
restore_saved_node_id_states (saved_node_id_states);
if (else_node_id_ref_counts!=NULL)
add_else_ref_counts (else_node_id_ref_counts);
}
void InitCoding (void)
{
int i;
NewLabelNr = 1;
SetUnaryState (& StrictOnAState, StrictOnA, UnknownObj);
SetUnaryState (& OnAState, OnA, UnknownObj);
SetUnaryState (& UnderEvalState, UnderEval, UnknownObj);
SetUnaryState (& ProcIdState, OnB, ProcIdObj);
ApplyDef=MakeNewSymbolDefinition ("system", ApplyId, 2, DEFRULE);
ApplyDef->sdef_number=0;
IfDef=MakeNewSymbolDefinition ("system", IfId, 3, DEFRULE);
IfDef->sdef_number=0;
InitBasicDescriptor (UnknownObj, "_", SizeOfAStackElem);
#if ABSTRACT_OBJECT
InitBasicDescriptor (AbstractObj, "_", SizeOfAStackElem);
#endif
InitBasicDescriptor (IntObj, "INT", SizeOfInt);
InitBasicDescriptor (BoolObj, "BOOL", SizeOfBool);
InitBasicDescriptor (CharObj, "CHAR", SizeOfChar);
InitBasicDescriptor (StringObj, "STRING", SizeOfAStackElem);
InitBasicDescriptor (RealObj, "REAL", SizeOfReal);
InitBasicDescriptor (FileObj, "FILE", SizeOfFile);
InitBasicDescriptor (ArrayObj, "ARRAY", SizeOfAStackElem);
InitBasicDescriptor (UnboxedArrayObj, "ARRAY", SizeOfAStackElem);
InitBasicDescriptor (WorldObj, "WORLD", SizeOfAStackElem);
InitBasicDescriptor (ProcIdObj, "PROCID", SizeOfProcId);
InitBasicDescriptor (RedIdObj, "REDID", SizeOfInt);
for (i=0; i<MaxNodeArity-NrOfGlobalSelectors; i++)
LazyTupleSelectors [i] = False;
next_update_function_n=0;
next_match_function_n=0;
}