aboutsummaryrefslogblamecommitdiff
path: root/backendC/CleanCompilerSources/backend.c
blob: 8a77f8fa561d9fe045b4c83e95015d5231917aa8 (plain) (tree)
1
2
3
4
5
6
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018

                        
                            
                    












                                                                                                              
                                                      







                            
      

                     






                                                                             

                                                              
































































































                                                                   


                                                              
























































































































                                                                                                                         
















                                                                                 






































































                                                                                                                                   
                               
                                                     


                                                      







                                                                                                 
                                                                   
 

                                                    

                                                             
                                                                                          


                                                                     
                                                                          
                                            


                                                                  
                                                                                                    



















                                                                                                                   
                                                                                                                                                                 
















                                                                                                                                      
                            




                                                             




                                                         





                                                                                                       

                                                              
                                                      













                                                                                          
                  


                                                                                                   

                                                               











                                                                       
                                                                                                                                          
                                                                                                                           
                                                                                        















































































































































































































































                                                                                                                                                                                 
                                                                                                                                 




























































































































































































                                                                                                                                                                                  
                                             












































                                                                                   
                                                                                                       
                                                                                                                              
                                                                                             




















































                                                                       
                                                 
                



                                                                                                                                          





                                                                   
                                                    


                                                                             
                                             
                                                       

                                                                                        
 
                                                                                                                            





                                                                   
                                                    



                                                               
                                         

                                                       




























































































































































































                                                                                                                                                              
      









































































                                                                                                      
 







                                                                      























































                                                                      



























                                                                  
                                                                                  







                                                                               
                                                                                     





















































                                                                                    
                            





















                                                                                                    
                                 

























                                                             
                                            












                                                                  
                                                                                     
                                            
                                            






















                                                                                                                                                                   
                                                                                                     
                                                            
 



















                                                                                                                         

                      


















                                                                     






















































































































































                                                                                                                   
       









                                                     
                                                  


                            















































                                                                                        




                                                                                                                
 























                                                                                       
                                                                                               
                                                                







                                                                                 
 



                                                           

                                            
                                             
      
                                                  
                                            






                                                          
 



                                                                             
 
                                                          


                          











                                                                                
                                            





















                                                                                                          
                            














                                                           
                                            





















                                          































                                                                    
                                                    
                                                                         
                                            
























                                                                          






                                                      


















                                                               
                                                    



























































































                                                                             

























































                                                                                                      






                                                                                                                        
                                                                                 






















                                                                             
                                                                                 










































                                                                                                 
 

























                                                                                  
                                                           

                                                      
                                                         















































































                                                                                               
                                                           























































































                                                                                                  
 


                                                                 
                                                                                                                

                                               
                                                                            





































































                                                                            
                                            





















































































































































































































































































































































































                                                                                                 






























                                                                 




































































































                                                                                                                     


















                                                                                                            










                                                                      
                                                                   






























                                                                                              
                                                           














                                                                          
                                                                   































                                                                                                      
                                                                   
































                                                                                              
                                                                   


















































































































                                                                                                                     
                                                                                           







                                                                                          






















































                                                                                       



                                          


                                             
















                                                  


                                        



                                      
                        


                            


                                    





                                                                                    

























                                                                               
 













                                                                                             
#define CODE_INLINE_FLAG
#define DYNAMIC_TYPE 1

# include "compiledefines.h"
# include "types.t"
# include "system.h"
# include "syntaxtr.t"
# include "codegen_types.h"
# include "statesgen.h"
# include "codegen.h"
# include "codegen2.h"
# include "instructions.h"
# include "sizes.h"
# include "set_scope_numbers.h"

# include "scanner.h"		/* InitScanner, ScanInitIdentStringTable */
# include "checker.h"		/* scc_dependency_list, ClearOpenDefinitionModules, AddOpenDefinitionModule */
# include "comsupport.h" 	/* CurrentModule */
# include "buildtree.h"		/* TupleSymbol, ApplySymbol */

extern void InitARC_Info (void); /* from typeconv.h */

# include "backendsupport.h"
# define Clean(ignore)

# include "dynamics.h"

# include "backend.h"

# include <limits.h>

# if 0
# include "dbprint.h"
# endif

void
BEGetVersion (int *current, int *oldestDefinition, int *oldestImplementation)
{
	*current				= kBEVersionCurrent;
	*oldestDefinition		= kBEVersionOldestDefinition;
	*oldestImplementation	= kBEVersionOldestImplementation;
}

#if STRICT_LISTS
 PolyList unboxed_record_cons_list,unboxed_record_decons_list;
#endif

extern PolyList UserDefinedArrayFunctions;	/* typechecker.c */
extern StdOutReopened, StdErrorReopened;	/* cocl.c */

/*
	Strings
	=======
*/
static char *
ConvertCleanString (CleanString string)
{
	int		length;
	char	*copy;

	length	= string->length;
	copy	= ConvertAlloc (length+1);
	strncpy (copy, string->chars, length);
	copy [length]	= '\0';

	return (copy);
} /* ConvertCleanString */

/*
	Counting routines
*/

static short
CountTypeArgs (BETypeArgP args)
{
	short	n;

	n	= 0;
	for (; args != NULL; args = args->type_arg_next)
		n++;

	return (n);
} /* CountTypeArgs */

static short
CountArgs (BEArgP args)
{
	short	n;

	n	= 0;
	for (; args != NULL; args = args->arg_next)
		n++;

	return (n);
} /* CountArgs */

/*
	BE routines
*/
STRUCT (be_module, BEModule)
{
	char			*bem_name;
	Bool			bem_isSystemModule;

	unsigned int	bem_nFunctions;
	SymbolP			bem_functions;
	unsigned int	bem_nConstructors;

	unsigned int	bem_nTypes;
	SymbolP			*bem_types;

	SymbolP			*bem_constructors;

	unsigned int	bem_nFields;
	SymbolP			bem_fields;
};

STRUCT (be_icl_module, BEIcl)
{
	ImpMod			beicl_module;
	BEModuleS		beicl_dcl_module;

	// +++ remove this (build deps list separately)
	SymbDefP		*beicl_depsP;
	unsigned int	beicl_previousAncestor;
};

STRUCT (be_state, BEState)
{
	Bool			be_initialised;

	char			**be_argv;
	int				be_argc;
	int				be_argi;

	BEModuleP		be_modules;

	BEIclS			be_icl;
	unsigned int	be_nModules;

	SymbolP			be_allSymbols;
	SymbolP			be_dontCareSymbol;
	SymbolP			be_dictionarySelectFunSymbol;
	SymbolP			be_dictionaryUpdateFunSymbol;

	// temporary hack
	int				be_dynamicTypeIndex;
	int				be_dynamicModuleIndex;
};

static BEStateS	gBEState = {False /* ... */};

/* +++ dynamic allocation */
# define	kMaxNumberOfNodeIds	1000

STRUCT (be_locally_generated_function_info, BELocallyGeneratedFunction)
{
	char	*lgf_name;
	int		lgf_arity;
};

static BELocallyGeneratedFunctionS gLocallyGeneratedFunctions[] = {{"_dictionary_select", 3}, {"_dictionary_update", 4}};
# define	kDictionarySelect	0
# define	kDictionaryUpdate	1

// +++ put in gBEState
static NodeIdP	gCurrentNodeIds [kMaxNumberOfNodeIds];
static SymbolP	gBasicSymbols [Nr_Of_Predef_FunsOrConses];
static SymbolP	gTupleSelectSymbols [MaxNodeArity];

static int number_of_node_ids=0;

static IdentP
Identifier (char *name)
{
	IdentP	ident;

	ident	= ConvertAllocType (IdentS);
	ident->ident_name	= name;

	return (ident);
} /* Identifier */

static SymbolP
PredefinedSymbol (SymbKind symbolKind, int arity)
{
	SymbolP	symbol;

	symbol	= ConvertAllocType (SymbolS);

	symbol->symb_kind	= symbolKind;
	symbol->symb_arity	= arity;

	return (symbol);
} /* PredefinedSymbol */

static SymbolP
AllocateSymbols (int nSymbols, SymbolP otherSymbols)
{
	int		i;
	SymbolP	symbols;

	if (nSymbols > 0)
	{
		symbols	= (SymbolP) ConvertAlloc (nSymbols * sizeof (SymbolS));
	
		for (i = 0; i < nSymbols; i++)
		{
			symbols [i].symb_kind	= erroneous_symb;
			symbols [i].symb_next	= &symbols [i+1];
		}
		symbols [nSymbols-1].symb_next	= otherSymbols;
	}
	else
		symbols	= otherSymbols;

	return (symbols);
} /* AllocateSymbols */

static void
InitPredefinedSymbols (void)
{
	int	i;

	gBasicSymbols [int_type]		= PredefinedSymbol (int_type, 0);
	gBasicSymbols [bool_type]		= PredefinedSymbol (bool_type, 0);
	gBasicSymbols [char_type]		= PredefinedSymbol (char_type, 0);
	gBasicSymbols [real_type]		= PredefinedSymbol (real_type, 0);
	gBasicSymbols [file_type]		= PredefinedSymbol (file_type, 0);
	gBasicSymbols [world_type]		= PredefinedSymbol (world_type, 0);
#if DYNAMIC_TYPE
	gBasicSymbols [dynamic_type]= PredefinedSymbol (dynamic_type, 0);
#endif
	gBasicSymbols [array_type]			= PredefinedSymbol (array_type, 1);
	gBasicSymbols [strict_array_type]	= PredefinedSymbol (strict_array_type, 1);
	gBasicSymbols [unboxed_array_type]	= PredefinedSymbol (unboxed_array_type, 1);

	gBasicSymbols [fun_type]	= PredefinedSymbol (fun_type, 2);


	ApplySymbol	= PredefinedSymbol (apply_symb, 2);
	gBasicSymbols [apply_symb]	= ApplySymbol;

	TupleSymbol	= PredefinedSymbol (tuple_symb, 2); /* arity doesn't matter */
	gBasicSymbols [tuple_symb]	= TupleSymbol;
	gBasicSymbols [tuple_type]	= PredefinedSymbol (tuple_type, 2);

	gBasicSymbols [if_symb]		= PredefinedSymbol (if_symb, 3);
	gBasicSymbols [fail_symb]	= PredefinedSymbol (fail_symb, 0);

	gBasicSymbols [nil_symb]	= PredefinedSymbol (nil_symb, 0);
	gBasicSymbols [cons_symb]	= PredefinedSymbol (cons_symb, 2);

	for (i = 0; i < MaxNodeArity; i++)
		gTupleSelectSymbols [i]	= NULL;

} /* InitPredefinedSymbols */

static void
AddUserDefinedArrayFunction (SymbolP functionSymbol)
{
	PolyList	elem;

	elem	= ConvertAllocType (struct poly_list);

	elem->pl_elem	= functionSymbol;
	elem->pl_next	= UserDefinedArrayFunctions;
	UserDefinedArrayFunctions	= elem;
} /* AddUserDefinedArrayFunction */

static Node
NewGuardNode (NodeP ifNode, NodeP node, NodeDefP nodeDefs, StrictNodeIdP stricts)
{
	NodeP	guardNode;
	
	guardNode	= ConvertAllocType (NodeS);
	
	guardNode->node_kind		= GuardNode;
	guardNode->node_node_defs	= nodeDefs;
	guardNode->node_arity		= 2;
	guardNode->node_guard_strict_node_ids	= stricts;

	guardNode->node_arguments	= BEArgs (ifNode, BEArgs (node, NULL));
	
	return (guardNode);
} /* NewGuardNode */


static void
DeclareModule (int moduleIndex, char *name, Bool isSystemModule, int nFunctions,
											int nTypes, int nConstructors, int nFields)
{
	BEModuleP	module;
	SymbolP		symbols, allSymbols;

	allSymbols	= gBEState.be_allSymbols;

	allSymbols	= AllocateSymbols (nFunctions + nTypes + nConstructors + nFields, allSymbols);

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	module->bem_name			= name;
	module->bem_isSystemModule	= isSystemModule;

	symbols	= allSymbols;

	module->bem_nFunctions	= (unsigned int) nFunctions;
	module->bem_functions	= symbols;
	symbols	+=	nFunctions;

	module->bem_nTypes	= (unsigned int) nTypes;
//	module->bem_types	= symbols;
	{
		/* +++ do this lazily */
		int	i;
		
		module->bem_types	= (SymbolP *) ConvertAlloc (nTypes * sizeof (SymbolP));

		for (i = 0; i < nTypes; i++)
		{
			module->bem_types [i]	= &symbols [i];
		}
	}
	{
		/* +++ change this */
		int		i;
		for (i = 0; i < nTypes; i++)
		{
			SymbDef	newSymbDef;

			newSymbDef	= ConvertAllocType (SymbDefS);
			newSymbDef->sdef_isused	= False;
			symbols [i].symb_def	= newSymbDef;
		}
	}
	symbols	+=	nTypes;

	module->bem_nConstructors	= (unsigned int) nConstructors;
//	module->bem_constructors	= symbols;
	{
		/* +++ do this lazily */
		int	i;
		
		module->bem_constructors	= (SymbolP *) ConvertAlloc (nConstructors * sizeof (SymbolP));

		for (i = 0; i < nConstructors; i++)
		{
			module->bem_constructors [i]	= &symbols [i];
		}
	}
	symbols	+=	nConstructors;

	module->bem_nFields	= (unsigned int) nFields;
	module->bem_fields	= symbols;
	symbols	+=	nFields;

	gBEState.be_allSymbols	= allSymbols;
} /* DeclareModule */

static int main_dcl_module_n=0;

void
BESetMainDclModuleN (int main_dcl_module_n_parameter)
{
	main_dcl_module_n=main_dcl_module_n_parameter;
}

void
BEDeclareIclModule (CleanString name, int nFunctions, int nTypes, int nConstructors, int nFields)
{
	int		i;
	char	*cName;
	SymbolP	moduleNameSymbol;
	ImpMod	iclModule;
	BEIclP	icl;

	cName	= gBEState.be_modules [main_dcl_module_n].bem_name;

	if (cName == NULL)
		cName	= ConvertCleanString (name);

	moduleNameSymbol	= ConvertAllocType (SymbolS);
	moduleNameSymbol->symb_ident	= Identifier (cName);

/*	Assert (strcmp (gBEState.be_modules [main_dcl_module_n].bem_name, cName) == 0); */
	Assert (strncmp (cName, name->chars, name->length) == 0);

	icl	= &gBEState.be_icl;

	icl->beicl_module		= ConvertAllocType (ImpRepr);
	icl->beicl_dcl_module	= gBEState.be_modules [main_dcl_module_n];
	icl->beicl_previousAncestor	= 0;
	scc_dependency_list	= NULL;
	icl->beicl_depsP	= &scc_dependency_list;

	nFunctions	+= ArraySize (gLocallyGeneratedFunctions);
	DeclareModule (main_dcl_module_n, cName, False, nFunctions, nTypes, nConstructors, nFields);

	iclModule	= icl->beicl_module;
	iclModule->im_name			= moduleNameSymbol;
	iclModule->im_def_module	= NULL;
	iclModule->im_rules			= NULL;
	iclModule->im_start			= NULL;
	iclModule->im_symbols		= gBEState.be_allSymbols;
# if IMPORT_OBJ_AND_LIB
	iclModule->im_imported_objs	= NULL;
	iclModule->im_imported_libs	= NULL;
# endif

	CurrentModule	= cName;

	for (i = 0; i < ArraySize (gLocallyGeneratedFunctions); i++)
	{
		static void	DeclareFunctionC (char *name, int arity, int functionIndex, unsigned int ancestor);
		BELocallyGeneratedFunctionP	locallyGeneratedFunction;

		locallyGeneratedFunction	= &gLocallyGeneratedFunctions [i];

		DeclareFunctionC (locallyGeneratedFunction->lgf_name, locallyGeneratedFunction->lgf_arity, nFunctions-ArraySize(gLocallyGeneratedFunctions)+i,0);
	}

	/* +++ hack */
	{
		static BESymbolP CreateDictionarySelectFunSymbol (void);
		static BESymbolP CreateDictionaryUpdateFunSymbol (void);

		gBEState.be_dictionarySelectFunSymbol	= CreateDictionarySelectFunSymbol ();
		gBEState.be_dictionaryUpdateFunSymbol	= CreateDictionaryUpdateFunSymbol ();
	}
} /* BEDeclareIclModule */

void
BEDeclareDclModule (int moduleIndex, CleanString name, int isSystemModule, int nFunctions, int nTypes, int nConstructors, int nFields)
{
	char	*cName;
	SymbolP	moduleNameSymbol;
	DefMod	dclModule;
	SymbolP	saveSymbols;

	cName	= ConvertCleanString (name);

	moduleNameSymbol	= ConvertAllocType (SymbolS);
	moduleNameSymbol->symb_ident	= Identifier (cName);

	if (moduleIndex == main_dcl_module_n)
	{
		saveSymbols	= gBEState.be_allSymbols;
		gBEState.be_allSymbols	= NULL;
	}

	DeclareModule (moduleIndex, cName, isSystemModule, nFunctions, nTypes, nConstructors, nFields);

	dclModule	= ConvertAllocType (DefRepr);
	dclModule->dm_name			= moduleNameSymbol;
	dclModule->dm_system_module	= isSystemModule;
	dclModule->dm_symbols		= gBEState.be_allSymbols; /* ??? too many symbols? */

	AddOpenDefinitionModule (moduleNameSymbol, dclModule);

	if (moduleIndex == main_dcl_module_n)
		gBEState.be_allSymbols	= saveSymbols;
} /* BEDeclareDclModule */

void
BEDeclarePredefinedModule (int nTypes, int nConstructors)
{
	char	*cName;

	cName	= "_predef";

	DeclareModule (kPredefinedModuleIndex, cName, False, 0, nTypes, nConstructors, 0);
} /* BEDeclarePredefinedModule */

void
BEDeclareModules (int nModules)
{
	int	i;

	Assert (gBEState.be_modules == NULL);

	gBEState.be_nModules	= (unsigned int) nModules;
	gBEState.be_modules		= (BEModuleP) ConvertAlloc (nModules * sizeof (BEModuleS));

	for (i = 0; i < nModules; i++)
		gBEState.be_modules [i].bem_name	= NULL;
} /* BEDeclareModules */

BESymbolP
BEFunctionSymbol (int functionIndex, int moduleIndex)
{
	BEModuleP	module;
	SymbolP		functionSymbol;

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) functionIndex < module->bem_nFunctions);
	functionSymbol	= &module->bem_functions [functionIndex];
	Assert (functionSymbol->symb_kind == definition || functionSymbol->symb_kind == cons_symb || functionSymbol->symb_kind == nil_symb
				|| (moduleIndex == kPredefinedModuleIndex && functionSymbol->symb_kind != erroneous_symb));

	if (functionSymbol->symb_kind!=cons_symb && functionSymbol->symb_kind!=nil_symb)
		functionSymbol->symb_def->sdef_isused	= True;

	return (functionSymbol);
} /* BEFunctionSymbol */

static void
GetArrayFunctionType (SymbDefP sdef, TypeNode *elementTypeP, TypeNode *arrayTypeP)
{
	TypeAlt		*typeAlt;

	typeAlt	= sdef->sdef_rule_type->rule_type_rule;

	switch (sdef->sdef_arfun)
	{
		case BEArraySelectFun:
		case BEUnqArraySelectFun:
		case BE_UnqArraySelectFun:
		case BE_UnqArraySelectNextFun:
		case BE_UnqArraySelectLastFun:
			break;
		case BEArrayUpdateFun:
		case BE_ArrayUpdateFun:
			Assert (typeAlt->type_alt_lhs->type_node_arity == 3);
			*elementTypeP	= typeAlt->type_alt_lhs->type_node_arguments->type_arg_next->type_arg_next->type_arg_node;
			*arrayTypeP	= typeAlt->type_alt_lhs->type_node_arguments->type_arg_node;
			break;
		default:
			*elementTypeP	= NULL;
			*arrayTypeP		= NULL;
			break;
	}
} /* GetArrayFunctionType */

BESymbolP
BESpecialArrayFunctionSymbol (BEArrayFunKind arrayFunKind, int functionIndex, int moduleIndex)
{
	Bool		isSpecialArrayFunction;
	BEModuleP	module;
	SymbolP		functionSymbol;
	SymbDefP	sdef;
	SymbDefP	originalsdef;
	TypeAlt		*typeAlt;
	TypeNode	elementType, arrayType;

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) functionIndex < module->bem_nFunctions);
	functionSymbol	= &module->bem_functions [functionIndex];
	Assert (functionSymbol->symb_kind == definition
				|| (moduleIndex == kPredefinedModuleIndex && functionSymbol->symb_kind != erroneous_symb));

	originalsdef	= functionSymbol->symb_def;

	typeAlt	= originalsdef->sdef_rule_type->rule_type_rule;
	isSpecialArrayFunction	= False;
	switch (arrayFunKind)
	{
		case BEArraySelectFun:
			Assert (originalsdef->sdef_arfun == BEArraySelectFun || originalsdef->sdef_arfun == BEUnqArraySelectFun);
			break;
		case BE_UnqArraySelectFun:
		case BE_UnqArraySelectLastFun:
			Assert (typeAlt->type_alt_lhs->type_node_arity == 2);
			elementType	= typeAlt->type_alt_rhs;
			arrayType	= typeAlt->type_alt_lhs->type_node_arguments->type_arg_node;

			isSpecialArrayFunction	= True;
			Assert (originalsdef->sdef_arfun == BEArraySelectFun);
			break;
		case BE_ArrayUpdateFun:
			isSpecialArrayFunction	= True;
			elementType	= typeAlt->type_alt_lhs->type_node_arguments->type_arg_next->type_arg_next->type_arg_node;
			arrayType	= typeAlt->type_alt_lhs->type_node_arguments->type_arg_node;
			/* fall through! */
		case BEArrayUpdateFun:
			Assert (originalsdef->sdef_arfun == BEArrayUpdateFun);
			break;
		default:
			Assert (False);
			break;
	}

	if (isSpecialArrayFunction)
	{
		SymbolP	previousFunctionSymbol;
		Bool	allreadyCreated;

		previousFunctionSymbol	= functionSymbol;
		functionSymbol	= functionSymbol->symb_next;

		allreadyCreated	= False;
		if (functionSymbol != NULL && functionSymbol->symb_kind == definition)
		{
			sdef			= functionSymbol->symb_def;
			allreadyCreated	= sdef->sdef_arfun == (ArrayFunKind) arrayFunKind;
			if (!allreadyCreated && arrayFunKind == BE_UnqArraySelectLastFun && sdef->sdef_arfun == BE_UnqArraySelectFun)
			{
				previousFunctionSymbol	= functionSymbol;
				functionSymbol	= functionSymbol->symb_next;
	
				if (functionSymbol != NULL && functionSymbol->symb_kind == definition)
				{
					sdef			= functionSymbol->symb_def;
					allreadyCreated	= sdef->sdef_arfun == (ArrayFunKind) arrayFunKind;
				}
			}
		}

		if (!allreadyCreated)
		{
			char		*functionName, *functionPrefix;
			TypeAlt		*newTypeAlt;
			IdentP		newIdent;
			SymbDefP	newsdef;
			SymbolP		newFunctionSymbol;
			RuleTypes	newRuleType;
			TypeArgs	lhsArgs;
			TypeNode	rhs;

			newFunctionSymbol	= ConvertAllocType (SymbolS);
			newsdef				= ConvertAllocType (SymbDefS);
			newIdent			= ConvertAllocType (IdentS);

			newTypeAlt	= ConvertAllocType (TypeAlt);

			newTypeAlt->type_alt_type_context	= NULL;	/* used in PrintType */
			newTypeAlt->type_alt_attr_equations	= NULL; /* used in PrintType */

			Assert (!arrayType->type_node_is_var);
			switch (arrayType->type_node_symbol->symb_kind)
			{
				case strict_array_type:
				case unboxed_array_type:
					elementType->type_node_annotation	= StrictAnnot;
					break;
				case array_type:
					break;
				default:
					Assert (False);
					break;
			}

			switch (arrayFunKind)
			{
				case BE_UnqArraySelectFun:
					rhs	= BENormalTypeNode (gBasicSymbols [tuple_type],
												BETypeArgs (elementType, BETypeArgs (arrayType, NULL)));
					lhsArgs	= BETypeArgs (arrayType, BETypeArgs (BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [int_type], NULL)), NULL));
					functionPrefix	= "_uselectf";
					break;
				case BE_UnqArraySelectLastFun:
				{
					struct clean_string	rName = {1, 'r'};
					TypeNode			rType;

					rType	= BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&rName));
					rhs	= BENormalTypeNode (gBasicSymbols [tuple_type],
												BETypeArgs (elementType, BETypeArgs (rType, NULL)));
					lhsArgs	= BETypeArgs (
								BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [tuple_type],
										BETypeArgs (arrayType, BETypeArgs (rType, NULL)))),
								BETypeArgs (BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [int_type], NULL)), NULL));
					functionPrefix	= "_uselectl";
					break;
				}
				case BE_ArrayUpdateFun:
				{
					struct clean_string	rName = {1, 'r'};
					TypeNode			rType;

					rType	= BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&rName));
					rhs	= rType;
					lhsArgs	= BETypeArgs (
								BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [tuple_type],
										BETypeArgs (arrayType, BETypeArgs (rType, NULL)))),
								BETypeArgs (BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [int_type], NULL)),
								BETypeArgs (elementType,
								NULL)));
					functionPrefix	= "_updatei";
					break;
				}
				default:
					Assert (False);
					break;
			}

			functionName	= ConvertAlloc (strlen (functionPrefix) + 1 + strlen (originalsdef->sdef_ident->ident_name) + 1);
			strcpy (functionName, functionPrefix);
			strcat (functionName, ";");
			strcat (functionName, originalsdef->sdef_ident->ident_name);

			newTypeAlt->type_alt_lhs	= BENormalTypeNode (newFunctionSymbol, lhsArgs);
			newTypeAlt->type_alt_rhs	= rhs;

			newIdent->ident_symbol	= newFunctionSymbol;
			newIdent->ident_name	= functionName;

			newRuleType	= ConvertAllocType (struct rule_type);
			newRuleType->rule_type_rule	= newTypeAlt;

			newsdef->sdef_ident			= newIdent;
			newsdef->sdef_module		= gBEState.be_icl.beicl_module->im_name->symb_def->sdef_module; /* phew! */
			newsdef->sdef_over_arity	= 0;
			newsdef->sdef_isused		= True;
			newsdef->sdef_exported		= False;
			newsdef->sdef_arity			= newTypeAlt->type_alt_lhs->type_node_arity;
			newsdef->sdef_arfun			= arrayFunKind;
			newsdef->sdef_kind 			= SYSRULE;
			newsdef->sdef_rule_type		= newRuleType;
			newsdef->sdef_ident			= newIdent;
			newsdef->sdef_mark			= 0;

			newFunctionSymbol->symb_kind	= definition;
			newFunctionSymbol->symb_def		= newsdef;

			functionSymbol						= previousFunctionSymbol->symb_next;
			previousFunctionSymbol->symb_next	= newFunctionSymbol;
			newFunctionSymbol->symb_next		= functionSymbol;

			AddUserDefinedArrayFunction (newFunctionSymbol);

			functionSymbol	= newFunctionSymbol;
		}

	}

	return (functionSymbol);
} /* BESpecialArrayFunctionSymbol */

static SymbolP
CreateLocallyDefinedFunction (int index, char ** abcCode, TypeArgs lhsArgs, TypeNode rhsType)
{
	int				i, arity, functionIndex;
	NodeP			lhs;
	BEStringListP	instructions, *instructionsP;
	BECodeBlockP	codeBlock;
	RuleAltP		ruleAlt;
	SymbolP			functionSymbol;
	TypeAlt			*typeAlt;
	ArgP			args;

	functionIndex	= gBEState.be_modules[main_dcl_module_n].bem_nFunctions - ArraySize (gLocallyGeneratedFunctions) + index;
	functionSymbol	= BEFunctionSymbol (functionIndex, main_dcl_module_n);
	functionSymbol->symb_def->sdef_isused	= False;

	instructionsP	= &instructions;
	for (i = 0; abcCode [i] != NULL; i++)
	{
		BEStringListP	string;

		string	= ConvertAllocType (struct string_list);

		string->sl_string	= abcCode [i];
		string->sl_next		= instructions;

		*instructionsP	= string;
		instructionsP	= &string->sl_next;
	}
	*instructionsP	=	NULL;

	codeBlock	= BEAbcCodeBlock (False, instructions);
		
	lhs		= BENormalNode (functionSymbol, NULL);
	arity	= CountTypeArgs (lhsArgs);

	args	= NULL;
	for (i = 0; i < arity; i++)
		args	= BEArgs (BENodeIdNode (BEWildCardNodeId (), NULL), args);

	lhs->node_arguments	= args;
	lhs->node_arity		= arity;

	Assert (arity == functionSymbol->symb_def->sdef_arity);

	ruleAlt		= BECodeAlt (0, NULL, lhs, codeBlock);

	typeAlt	= ConvertAllocType (TypeAlt);

	typeAlt->type_alt_type_context	= NULL;	/* used in PrintType */
	typeAlt->type_alt_attr_equations	= NULL; /* used in PrintType */
	typeAlt->type_alt_lhs	= BENormalTypeNode (functionSymbol, lhsArgs);
	typeAlt->type_alt_rhs	= rhsType;

	BERule (functionIndex, BEIsNotACaf, typeAlt, ruleAlt);
	
	return (functionSymbol);
} /* CreateLocallyDefinedFunction */

static BESymbolP
CreateDictionarySelectFunSymbol (void)
{
	TypeNode		rhsType;
	TypeArgs		lhsArgs;
	struct clean_string	aName = {1, 'a'};

	/* selectl :: !((a e) Int -> e) !(!a e, !r) !Int -> (e, !r) */
	/* select _ _ _ = code */
	static char *abcCode[] = {
		"push_a 1",
		"push_a 1",
		"build e_system_dAP 2 e_system_nAP",
		"buildI_b 0",
		"push_a 1",
		"update_a 1 2",
		"update_a 0 1",
		"pop_a 1",
		"build e_system_dAP 2 e_system_nAP",
		"push_a 3",
		"push_a 1",
		"update_a 1 2",
		"update_a 0 1",
		"pop_a 1",
		"update_a 1 4",
		"update_a 0 3",
		"pop_a 3",
		"pop_b 1",
		NULL
	};

	/*	actual type simplified to !a !(!a,!a) !Int -> (a,!a) */
	lhsArgs	=	BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
				BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [tuple_type],
								BETypeArgs (
									BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
								BETypeArgs (
									BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
								NULL)))),
				BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [int_type], NULL)),
				NULL)));
	rhsType	= BENormalTypeNode (gBasicSymbols [tuple_type],
								BETypeArgs (BEVarTypeNode (&aName), BETypeArgs (BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)), NULL)));

	return (CreateLocallyDefinedFunction (kDictionarySelect, abcCode, lhsArgs, rhsType));
} /* CreateDictionarySelectFunSymbol */

static BESymbolP
CreateDictionaryUpdateFunSymbol (void)
{
	TypeNode		rhsType;
	TypeArgs		lhsArgs;
	struct clean_string	aName = {1, 'a'};

	/* updatei :: !(*(a .e) -> *(!Int -> *(.e -> .(a .e)))) !(!*(a .e), !*r) !Int .e -> *r // !(!.(a .e), !*r) */
	/* updatei _ _ _ _ = code */
	static char *abcCode[] = {
		"	push_a 1",
		"	push_a 1",
		"	build _Nil 0 _hnf",
		"	update_a 0 4",
		"	pop_a 1",
		".d 2 0",
		"	jsr e_system_sAP",
		".o 1 0",
		"	buildI_b 0",
		"	push_a 1",
		"	update_a 1 2",
		"	update_a 0 1",
		"	pop_a 1",
		"	pop_b 1",
		".d 2 0",
		"	jsr e_system_sAP",
		".o 1 0",
		"	push_a 4",
		"	push_a 1",
		"	update_a 1 2",
		"	update_a 0 1",
		"	pop_a 1",
		"	build _Nil 0 _hnf",
		"	update_a 0 6",
		"	pop_a 1",
		".d 2 0",
		"	jsr e_system_sAP",
		".o 1 0",
		"	update_a 3 4",
		"	pop_a 4",
		NULL
	};

	/*	actual type simplified to !a !(!a,!a) !Int a -> a */
	lhsArgs	=	BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
				BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [tuple_type],
								BETypeArgs (
									BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
								BETypeArgs (
									BEAnnotateTypeNode (StrictAnnot, BEVarTypeNode (&aName)),
								NULL)))),
				BETypeArgs (
					BEAnnotateTypeNode (StrictAnnot, BENormalTypeNode (gBasicSymbols [int_type], NULL)),
				BETypeArgs (
					BEVarTypeNode (&aName),
				NULL))));

	rhsType	= BEVarTypeNode (&aName);

	return (CreateLocallyDefinedFunction (kDictionaryUpdate, abcCode, lhsArgs, rhsType));
} /* CreateDictionaryUpdateFunSymbol */

BESymbolP
BEDictionarySelectFunSymbol (void)
{
	gBEState.be_dictionarySelectFunSymbol->symb_def->sdef_isused	= True;

	return (gBEState.be_dictionarySelectFunSymbol);
} /* BEDictionarySelectFunSymbol */

BESymbolP
BEDictionaryUpdateFunSymbol (void)
{
	gBEState.be_dictionaryUpdateFunSymbol->symb_def->sdef_isused	= True;

	return (gBEState.be_dictionaryUpdateFunSymbol);
} /* BEDictionaryUpdateFunSymbol */

BESymbolP
BETypeSymbol (int typeIndex, int moduleIndex)
{
	BEModuleP	module;
	SymbolP		typeSymbol;

	if ((unsigned int) moduleIndex >= gBEState.be_nModules)
		Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) typeIndex < module->bem_nTypes);
	typeSymbol	= module->bem_types [typeIndex];
/*	Assert (typeSymbol->symb_kind == definition
				|| (moduleIndex == kPredefinedModuleIndex && typeSymbol->symb_kind != erroneous_symb));
*/
	if (moduleIndex == main_dcl_module_n)
		typeSymbol->symb_def->sdef_isused	= True;

	return (typeSymbol);
} /* BETypeSymbol */

BESymbolP
BEDontCareDefinitionSymbol (void)
{
	SymbolP	symbol;

	symbol	= gBEState.be_dontCareSymbol;
	if (symbol == NULL)
	{
		SymbDefP	symbDef;

		symbDef	= ConvertAllocType (SymbDefS);
		symbDef->sdef_kind	= ABSTYPE;

		symbDef->sdef_ident	= Identifier ("_Don'tCare"); /* +++ name */

		symbol	= ConvertAllocType (SymbolS);
		symbol->symb_kind	= definition;
		symbol->symb_def	= symbDef;

		gBEState.be_dontCareSymbol	= symbol;
	}

	return (symbol);
} /* BEDontCareDefinitionSymbol */

BESymbolP
BEConstructorSymbol (int constructorIndex, int moduleIndex)
{
	BEModuleP	module;
	SymbolP		constructorSymbol;

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) constructorIndex < module->bem_nConstructors);
	constructorSymbol	= module->bem_constructors [constructorIndex];

	/* RWS +++ hack for record constructors, remove this */
	if (constructorSymbol->symb_kind == erroneous_symb)
		return (constructorSymbol);

	Assert (constructorSymbol->symb_kind == definition || constructorSymbol->symb_kind == cons_symb
				|| (moduleIndex == kPredefinedModuleIndex && constructorSymbol->symb_kind != erroneous_symb));

	if (moduleIndex != kPredefinedModuleIndex && constructorSymbol->symb_kind!=cons_symb)
		constructorSymbol->symb_def->sdef_isused	= True;

	return (constructorSymbol);
} /* BEConstructorSymbol */

BESymbolP
BEFieldSymbol (int fieldIndex, int moduleIndex)
{
	BEModuleP	module;
	SymbolP		fieldSymbol;

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) fieldIndex < module->bem_nFields);
	fieldSymbol	= &module->bem_fields [fieldIndex];
	Assert (fieldSymbol->symb_kind == definition);

	fieldSymbol->symb_def->sdef_isused	= True;

	return (fieldSymbol);
} /* BEFieldSymbol */

BESymbolP
BEBoolSymbol (int value)
{
/* JVG: */
	if (value)
		return TrueSymbol;
	else
		return FalseSymbol;
/*
	SymbolP	symbol;
	
	symbol	= ConvertAllocType (SymbolS);
	symbol->symb_kind	= bool_denot;
	symbol->symb_bool	= value;

	return (symbol);
*/
} /* BEBoolSymbol */

BESymbolP
BELiteralSymbol (BESymbKind kind, CleanString value)
{
	SymbolP	symbol;

	symbol	= ConvertAllocType (SymbolS);
	symbol->symb_kind	= kind;
	symbol->symb_int	= ConvertCleanString (value);

	return (symbol);
} /* BELiteralSymbol */

# define	nid_ref_count_sign	nid_scope

#if STRICT_LISTS
static SymbolS unboxed_list_symbols[Nr_Of_Predef_Types][2];

static SymbolP strict_list_cons_symbols[8];

void BEPredefineListConstructorSymbol (int constructorIndex,int moduleIndex,BESymbKind symbolKind,int head_strictness,int tail_strictness)
{
	BEModuleP	module;
	SymbolP symbol_p;

	Assert (moduleIndex == kPredefinedModuleIndex);

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module = &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) constructorIndex < module->bem_nConstructors);
	
	symbol_p=module->bem_constructors [constructorIndex];

	symbol_p->symb_kind	= symbolKind;
	symbol_p->symb_head_strictness=head_strictness;
	symbol_p->symb_tail_strictness=tail_strictness;

	if (symbolKind==BEConsSymb && head_strictness<4)
		strict_list_cons_symbols[(head_strictness<<1)+tail_strictness]=symbol_p;
}

void BEPredefineListTypeSymbol (int typeIndex,int moduleIndex,BESymbKind symbolKind,int head_strictness,int tail_strictness)
{
	BEModuleP	module;
	SymbolP symbol_p;

	Assert (moduleIndex == kPredefinedModuleIndex);

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module = &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) typeIndex < module->bem_nTypes);

	symbol_p=module->bem_types [typeIndex];

	symbol_p->symb_kind = symbolKind;
	symbol_p->symb_arity = 1;
	symbol_p->symb_head_strictness=head_strictness;
	symbol_p->symb_tail_strictness=tail_strictness;
}

void BEAdjustStrictListConsInstance (int functionIndex,int moduleIndex)
{
	SymbolP symbol_p;

	symbol_p=&gBEState.be_modules[moduleIndex].bem_functions[functionIndex];

	if (symbol_p->symb_kind==definition){
		TypeNode element_type_p,list_type_p;
		SymbDef sdef;
		TypeArgs type_args_p;
		
		sdef=symbol_p->symb_def;
		type_args_p=sdef->sdef_rule_type->rule_type_rule->type_alt_lhs->type_node_arguments;
		element_type_p=type_args_p->type_arg_node;
		list_type_p=type_args_p->type_arg_next->type_arg_node;
		
		Assert (list_type_p->type_node_is_var==0);
		Assert (list_type_p->type_node_symbol->symb_kind==list_type);

		symbol_p->symb_head_strictness=list_type_p->type_node_symbol->symb_head_strictness;
		symbol_p->symb_tail_strictness=list_type_p->type_node_symbol->symb_tail_strictness;

		if (list_type_p->type_node_symbol->symb_head_strictness==3){
			int element_symbol_kind;
			struct unboxed_cons *unboxed_cons_p;

			Assert (element_type_p->type_node_is_var==0);

			element_symbol_kind=element_type_p->type_node_symbol->symb_kind;

			symbol_p->symb_head_strictness=4;

			unboxed_cons_p=ConvertAllocType (struct unboxed_cons);

			unboxed_cons_p->unboxed_cons_sdef_p=sdef;

			if (element_symbol_kind < Nr_Of_Predef_Types)
				unboxed_cons_p->unboxed_cons_state_p = unboxed_list_symbols[element_symbol_kind][symbol_p->symb_tail_strictness].symb_state_p;
			else if (element_symbol_kind==definition && element_type_p->type_node_symbol->symb_def->sdef_kind==RECORDTYPE){
				PolyList new_unboxed_record_cons_element;
				SymbDef record_sdef;
				
				record_sdef=element_type_p->type_node_symbol->symb_def;
				record_sdef->sdef_isused=True;
				sdef->sdef_isused=True;
				unboxed_cons_p->unboxed_cons_state_p = &record_sdef->sdef_record_state;
				
				new_unboxed_record_cons_element=ConvertAllocType (struct poly_list);
				new_unboxed_record_cons_element->pl_elem = sdef;
				new_unboxed_record_cons_element->pl_next = unboxed_record_cons_list;
				unboxed_record_cons_list = new_unboxed_record_cons_element;
				
				sdef->sdef_module=NULL;
			} else
				unboxed_cons_p->unboxed_cons_state_p = &StrictState;
			
			symbol_p->symb_unboxed_cons_p=unboxed_cons_p;
		}
	} else {
		Assert (symbol_p->symb_kind==definition);
		
		debug_message ("BEAdjustStrictListInstance: !(symbol_p->symb_kind==definition) %d %d %d\n",functionIndex,moduleIndex,symbol_p->symb_kind);

		symbol_p->symb_head_strictness=0;
		symbol_p->symb_tail_strictness=0;
	}
	
	symbol_p->symb_kind = cons_symb;
	/* symbol_p->symb_arity = 2; no symb_arity for cons_symb, because symb_state_p is used of this union */
}

void BEAdjustUnboxedListDeconsInstance (int functionIndex,int moduleIndex)
{
	SymbolP symbol_p,cons_symbol_p;
	SymbDefP sdef_p;
	TypeNode element_type_p,list_type_p;
	PolyList new_unboxed_record_decons_element;

	symbol_p=&gBEState.be_modules[moduleIndex].bem_functions[functionIndex];

	Assert (symbol_p->symb_kind==definition);
	sdef_p=symbol_p->symb_def;
	
	list_type_p=sdef_p->sdef_rule_type->rule_type_rule->type_alt_lhs->type_node_arguments->type_arg_node;
	element_type_p=list_type_p->type_node_arguments->type_arg_node;
	
	Assert (list_type_p->type_node_is_var==0);
	Assert (list_type_p->type_node_symbol->symb_kind==list_type);
	Assert (list_type_p->type_node_symbol->symb_head_strictness==3);
	Assert (element_type_p->type_node_symbol->symb_def->sdef_kind==RECORDTYPE);
	
	cons_symbol_p=ConvertAllocType (SymbolS);

	cons_symbol_p->symb_kind = cons_symb;
	cons_symbol_p->symb_head_strictness=4;
	cons_symbol_p->symb_tail_strictness=list_type_p->type_node_symbol->symb_tail_strictness;
	cons_symbol_p->symb_state_p=&element_type_p->type_node_symbol->symb_def->sdef_record_state;

	sdef_p->sdef_unboxed_cons_symbol=cons_symbol_p;
	
	new_unboxed_record_decons_element=ConvertAllocType (struct poly_list);
	new_unboxed_record_decons_element->pl_elem = sdef_p;
	new_unboxed_record_decons_element->pl_next = unboxed_record_decons_list;
	unboxed_record_decons_list = new_unboxed_record_decons_element;
}

void BEAdjustOverloadedNilFunction (int functionIndex,int moduleIndex)
{
	SymbolP symbol_p;

	symbol_p=&gBEState.be_modules[moduleIndex].bem_functions[functionIndex];

	symbol_p->symb_head_strictness=1;
	symbol_p->symb_tail_strictness=0;
	
	symbol_p->symb_kind = nil_symb;
}

BESymbolP BEOverloadedConsSymbol (int constructorIndex,int moduleIndex,int deconsIndex,int deconsModuleIndex)
{
	BEModuleP module,decons_module;
	SymbolP constructor_symbol,decons_symbol,list_type_symbol;
	TypeNode list_type,element_type;

	Assert ((unsigned int) deconsModuleIndex < gBEState.be_nModules);
	decons_module = &gBEState.be_modules [deconsModuleIndex];

	Assert ((unsigned int) deconsIndex < decons_module->bem_nFunctions);
	decons_symbol = &decons_module->bem_functions [deconsIndex];

	Assert (decons_symbol->symb_kind==definition);
	
	list_type=decons_symbol->symb_def->sdef_rule_type->rule_type_rule->type_alt_lhs->type_node_arguments->type_arg_node;
	element_type=list_type->type_node_arguments->type_arg_node;
	
	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module = &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) constructorIndex < module->bem_nConstructors);
	constructor_symbol = module->bem_constructors [constructorIndex];

	Assert (constructor_symbol->symb_kind==definition
				|| (moduleIndex==kPredefinedModuleIndex && constructor_symbol->symb_kind!=erroneous_symb));

	if (moduleIndex != kPredefinedModuleIndex)
		constructor_symbol->symb_def->sdef_isused = True;

	list_type_symbol=list_type->type_node_symbol;

	if (constructor_symbol->symb_head_strictness==1 && list_type_symbol->symb_head_strictness<4)
		constructor_symbol=strict_list_cons_symbols[(list_type_symbol->symb_head_strictness<<1)+list_type_symbol->symb_tail_strictness];

	if (list_type_symbol->symb_head_strictness==3){
		int element_symbol_kind;
		
		Assert (element_type->type_node_is_var==0);

		element_symbol_kind=element_type->type_node_symbol->symb_kind;

		if (element_symbol_kind<Nr_Of_Predef_Types)
			constructor_symbol=&unboxed_list_symbols[element_symbol_kind][list_type_symbol->symb_tail_strictness];
		else if (element_symbol_kind==definition && element_type->type_node_symbol->symb_def->sdef_kind==RECORDTYPE)
			constructor_symbol=decons_symbol->symb_def->sdef_unboxed_cons_symbol;
	}
	
	return constructor_symbol;
}

BENodeP BEOverloadedPushNode (int arity,BESymbolP symbol,BEArgP arguments,BENodeIdListP nodeIds,BENodeP decons_node)
{
	NodeP	push_node;

	push_node	= ConvertAllocType (NodeS);

	push_node->node_kind		= PushNode;
	push_node->node_arity		= arity;
	push_node->node_arguments	= arguments;
	push_node->node_push_symbol = symbol;
	push_node->node_decons_node = decons_node;
	push_node->node_node_ids	= nodeIds;
	push_node->node_number		= 0;

	Assert (arguments->arg_node->node_kind == NodeIdNode);
	Assert (arguments->arg_node->node_node_id->nid_ref_count_sign == -1);
		
	arguments->arg_node->node_node_id->nid_refcount++;
	
	return push_node;
}
#endif

void
BEPredefineConstructorSymbol (int arity, int constructorIndex, int moduleIndex, BESymbKind symbolKind)
{
	BEModuleP	module;

	Assert (moduleIndex == kPredefinedModuleIndex);

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) constructorIndex < module->bem_nConstructors);
	Assert (module->bem_constructors [constructorIndex]->symb_kind == erroneous_symb);

	module->bem_constructors [constructorIndex]->symb_kind	= symbolKind;
	module->bem_constructors [constructorIndex]->symb_arity	= arity;
} /* BEPredefineConstructorSymbol */

void
BEPredefineTypeSymbol (int arity, int typeIndex, int moduleIndex, BESymbKind symbolKind)
{
	BEModuleP	module;

	Assert (moduleIndex == kPredefinedModuleIndex);

	Assert ((unsigned int) moduleIndex < gBEState.be_nModules);
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) typeIndex < module->bem_nTypes);
	Assert (module->bem_types [typeIndex]->symb_kind == erroneous_symb);

	module->bem_types [typeIndex]->symb_kind		= symbolKind;
	module->bem_types [typeIndex]->symb_arity	= arity;
} /* BEPredefineTypeSymbol */

BESymbolP
BEBasicSymbol (BESymbKind kind)
{
	Assert (gBasicSymbols [kind] != NULL);

	return (gBasicSymbols [kind]);
} /* BEBasicSymbol */

BETypeNodeP
BEVarTypeNode (CleanString name)
{
	TypeNode	node;

	node	= ConvertAllocType (struct type_node);

	node->type_node_is_var		= True;
	node->type_node_tv			= BETypeVar (name);
	node->type_node_arity		= 0;
	node->type_node_annotation	= NoAnnot;
	node->type_node_attribute	= NoUniAttr;

	return (node);
} /* BEVarTypeNode */

BETypeNodeP
BENormalTypeNode (BESymbolP symbol, BETypeArgP args)
{
	TypeNode	node;

	node	= ConvertAllocType (struct type_node);

	node->type_node_is_var		= False;
	node->type_node_arity		= CountTypeArgs (args);
	node->type_node_annotation	= NoAnnot;
	node->type_node_attribute	= NoUniAttr;
	node->type_node_symbol		= symbol;
	node->type_node_arguments	= args;

	return (node);
} /* BENormalTypeNode */


BETypeNodeP
BEAttributeTypeNode (BEAttribution attribution, BETypeNodeP typeNode)
{
	Assert (typeNode->type_node_attribute == NoUniAttr);
	typeNode->type_node_attribute	= (AttributeKind) attribution;

	return (typeNode);
} /* BEAttributeTypeNode */

BEAttributeKindList
BEAttributeKind (BEAttribution attributeKind)
{
	AttributeKindList	new;

	new	= ConvertAllocType (struct attr_kind_list);

	new->akl_elem	= attributeKind;
	new->akl_next	= NULL;

	return (new);
} /* BEAttributeKind */

BEAttributeKindList
BENoAttributeKinds (void)
{
	return (NULL);
} /* BENoAttributeKinds */

BEAttributeKindList
BEAttributeKinds (BEAttributeKindList elem, BEAttributeKindList list)
{
	Assert (elem->akl_next == NULL);
	elem->akl_next	= list;

	return (elem);
} /* BEAttributeKindList */

BEUniVarEquations
BEUniVarEquation (BEAttribution demanded, BEAttributeKindList offered)
{
	UniVarEquations	new;

	new	= ConvertAllocType (struct uni_var_equats);

	new->uve_demanded	= demanded;
	new->uve_offered	= offered;
	new->uve_next		= NULL;

	return (new);
} /* BEUniVarEquation */

BEUniVarEquations
BENoUniVarEquations (void)
{
	return (NULL);
} /* BENoUniVarEquations */

BEUniVarEquations
BEUniVarEquationsList (BEUniVarEquations elem, BEUniVarEquations list)
{
	Assert (elem->uve_next == NULL);
	elem->uve_next	= list;

	return (elem);
} /* BEUniVarEquations */

BETypeNodeP
BEAnnotateTypeNode (BEAnnotation annotation, BETypeNodeP typeNode)
{
	Assert (typeNode->type_node_annotation == NoAnnot);
	typeNode->type_node_annotation	= (Annotation) annotation;

	return (typeNode);
} /* BEAnnotateTypeNode */

BETypeArgP
BENoTypeArgs (void)
{
	return (NULL);
} /* BENoTypeArgs */

BETypeArgP
BETypeArgs (BETypeNodeP node, BETypeArgP nextArgs)
{
	TypeArgs	arg;

	arg	= ConvertAllocType (TypeArg);

	arg->type_arg_node	= node;
	arg->type_arg_next	= nextArgs;

	return (arg);
} /* BETypeArgs */

BETypeAltP
BETypeAlt (BETypeNodeP lhs, BETypeNodeP rhs, BEUniVarEquations attributeEquations)
{
	TypeAlt	*alt;

	alt	= ConvertAllocType (struct type_alt);

	alt->type_alt_lhs	= lhs;
	alt->type_alt_rhs	= rhs;

	alt->type_alt_type_context		= NULL;	/* used in PrintType */
	alt->type_alt_attr_equations	= attributeEquations; /* used in PrintType */

	return (alt);
} /* BETypeAlt */

static Node
GenerateApplyNodes (Node root, int offarity, int demarity)
{
	if (offarity > demarity)
	{
		int		i;
		Args	lastarg, nextarg;
		
		if (demarity != 0)
		{
			for (i=1, lastarg = root->node_arguments; i < demarity; i++)
				lastarg = lastarg->arg_next;
		
			nextarg = lastarg->arg_next;
			lastarg->arg_next = NULL;
		}
		else
		{
			nextarg = root->node_arguments;
			root->node_arguments = NULL;
		}
		root->node_arity = (short) demarity;
		
		for (i=demarity+1; i<=offarity; i++)
		{
			Args	arg;

			arg	= BEArgs (root, nextarg);

   			nextarg	= nextarg->arg_next;
			arg->arg_next->arg_next = NULL;

			root	= BENormalNode (gBasicSymbols [apply_symb], arg);
		}
	}

	return (root);
} /* GenerateApplyNodes */

BENodeP
BENormalNode (BESymbolP symbol, BEArgP args)
{
	NodeP	node;

	node	= ConvertAllocType (NodeS);

	node->node_annotation	= NoAnnot;
	node->node_kind			= NormalNode;
	node->node_symbol		= symbol;
	node->node_arity		= CountArgs (args);
	node->node_arguments	= args;
	node->node_number=0;

	/* +++ hackerdiehack */
	if (symbol->symb_kind == definition)
		node	= GenerateApplyNodes (node, node->node_arity, symbol->symb_def->sdef_arity);

	return (node);
} /* BENormalNode */

BENodeP
BEMatchNode (int arity, BESymbolP symbol, BENodeP node)
{
	NodeP	matchNode;

	if (symbol->symb_kind == tuple_symb)
		return (node);

	matchNode	= ConvertAllocType (NodeS);

	matchNode->node_annotation	= NoAnnot;
	matchNode->node_kind		= MatchNode;
	matchNode->node_symbol		= symbol;
	matchNode->node_arity		= arity;
	matchNode->node_arguments	= BEArgs (node, NULL);
	matchNode->node_number=0;

	return (matchNode);
} /* BEMatchNode */

BENodeP
BETupleSelectNode (int arity, int index, BENodeP node)
{
	SymbolP symbol;
	NodeP	select;

	if ((symbol = gTupleSelectSymbols [arity-1]) == NULL)
	{
		symbol	= ConvertAllocType (SymbolS);
	
		symbol->symb_kind	= select_symb;
		symbol->symb_arity	= arity;

		gTupleSelectSymbols [arity-1]	= symbol;
	}

	select	= ConvertAllocType (NodeS);

	select->node_annotation	= NoAnnot;
	select->node_kind		= NormalNode;
	select->node_symbol		= symbol;
	select->node_arity		= index+1;
	select->node_arguments	= BEArgs (node, NULL);
	select->node_number		= 0;

	return (select);
} /* BETupleSelectNode */

BENodeP
BEIfNode (BENodeP cond, BENodeP then, BENodeP elsje)
{
	NodeP	node;

	node	= ConvertAllocType (NodeS);

	node->node_annotation	= NoAnnot;
	node->node_kind			= NormalNode;
	node->node_symbol		= gBasicSymbols [if_symb];
	node->node_arguments	= BEArgs (cond, BEArgs (then, BEArgs (elsje, NULL)));
	node->node_arity		= 3;
	node->node_number		= 0;

	return (node);
} /* BEIfNode */

BENodeP
BEGuardNode (BENodeP cond, BENodeDefP thenNodeDefs, BEStrictNodeIdP thenStricts, BENodeP then, BENodeDefP elseNodeDefs, BEStrictNodeIdP elseStricts, BENodeP elsje)
{
	NodeP	node;
	struct if_node_contents *thenElseInfo;

	thenElseInfo = ConvertAllocType (struct if_node_contents);

	thenElseInfo->if_then_node_defs			= thenNodeDefs;
	thenElseInfo->if_then_rules				= NIL;
	thenElseInfo->if_then_strict_node_ids	= thenStricts;
	thenElseInfo->if_else_node_defs			= elseNodeDefs;
	thenElseInfo->if_else_rules				= NIL;
	thenElseInfo->if_else_strict_node_ids	= elseStricts;

	node	= ConvertAllocType (NodeS);

	node->node_annotation			= NoAnnot;
	node->node_kind					= IfNode;
	node->node_contents.contents_if	= thenElseInfo;
	node->node_arguments			= BEArgs (cond, BEArgs (then, BEArgs (elsje, NULL)));
	node->node_number				= 0;

	switch (elsje->node_kind)
	{
		case SwitchNode:
			thenElseInfo->if_else_node_defs			= NULL;
			thenElseInfo->if_else_strict_node_ids	= NULL;
			node->node_arguments->arg_next->arg_next->arg_node
								= BENormalNode (BEBasicSymbol (BEFailSymb), BENoArgs ());

			node	= NewGuardNode (node, elsje, elseNodeDefs, elseStricts);
			break;
		case GuardNode:
			/* move the GuardNode to the top */
			node->node_arguments->arg_next->arg_next->arg_node
								= elsje->node_arguments->arg_node;
			elsje->node_arguments->arg_node	=	node;
			node	= elsje;
			break;
		default:
			break;
	}

	return (node);
} /* BEGuardNode */

static NodeIdRefCountListP
NewRefCount (NodeIdRefCountListP next, NodeIdP nodeId, int ref_count)
{
	NodeIdRefCountListP	newRefCount;

	newRefCount	= ConvertAllocType (NodeIdRefCountListS);

	newRefCount->nrcl_next		= next;
	newRefCount->nrcl_node_id	= nodeId;
	newRefCount->nrcl_ref_count	= ref_count;

	return (newRefCount);
} /* NewRefCount */

/* +++ dynamic allocation */
# define kMaxScope 1000
static int gCurrentScope = 0;
static	NodeIdRefCountListP	gRefCountLists [kMaxScope];
static	NodeIdRefCountListP	gRefCountList;

static void
AddRefCount (NodeIdP nodeId)
{
	gRefCountList	= NewRefCount (gRefCountList, nodeId, 0);
} /* AddRefCount */

void
BESetNodeDefRefCounts (BENodeP lhs)
{
	ArgP	arg;
	
	gRefCountList	= NULL;

	Assert (lhs->node_kind == NormalNode);

	for (arg = lhs->node_arguments; arg != NULL; arg = arg->arg_next)
	{
		NodeP	node;
		NodeIdP	nodeId;

		node	= arg->arg_node;

		Assert (node->node_kind == NodeIdNode);
		Assert (node->node_arguments == NULL);

		nodeId	= node->node_node_id;

		nodeId->nid_mark |= NID_ALIAS_MARK_MASK;
		AddRefCount (nodeId);
	}
} /* BESetNodeDefRefCounts */

void
BEAddNodeIdsRefCounts (int sequenceNumber, BESymbolP symbol, BENodeIdListP nodeIds)
{
	NodeIdP	nodeId;

	nodeId	= gCurrentNodeIds [sequenceNumber];

	Assert (nodeId != NULL);
	if (nodeId->nid_mark & NID_ALIAS_MASK)
	{
		nodeId	= nodeId->nid_forward_node_id;
		Assert (nodeId != NULL);
	}

	Assert (nodeId != NULL);

	if ((nodeId->nid_mark & NID_ALIAS_MARK_MASK)
			&&
				(symbol->symb_kind == tuple_symb
			 	|| (symbol->symb_kind == definition && symbol->symb_def->sdef_kind == RECORDTYPE)))
	{
		NodeP				node;
		ArgP				arg, args;
		NodeIdListElement	nodeIdList;

		node	= nodeId->nid_node;

		if (node == NULL)
		{
			NodeIdP	nid;

			nodeIdList	= nodeIds;

			nid	= nodeIdList->nidl_node_id;

			nid->nid_mark |= NID_ALIAS_MARK_MASK;

			args	= BEArgs (BENodeIdNode (nid, NULL), NULL);;

			for (nodeIdList = nodeIdList->nidl_next, arg = args;
					nodeIdList != NULL;
					nodeIdList = nodeIdList->nidl_next, arg	= arg->arg_next)
			{
				nid	= nodeIdList->nidl_node_id;

				nid->nid_mark |= NID_ALIAS_MARK_MASK;
				arg->arg_next	= BEArgs (BENodeIdNode (nid, NULL), NULL);
			}

			nodeId->nid_node	= BENormalNode (symbol, args);
		}
		else
		{	
			Assert (node->node_symbol == symbol);

			arg	= node->node_arguments;
			for (nodeIdList = nodeIds; nodeIdList != NULL && arg != NULL;
					nodeIdList = nodeIdList->nidl_next, arg = arg->arg_next)
			{
				Assert (arg->arg_node->node_kind == NodeIdNode);

				nodeId	= nodeIdList->nidl_node_id;

				nodeId->nid_mark |= NID_ALIAS_MASK;
				nodeId->nid_forward_node_id	= arg->arg_node->node_node_id;
				nodeIdList->nidl_node_id	= nodeId->nid_forward_node_id;
			}

			Assert (nodeIdList == NULL && arg == NULL);
		}
	}

	for (; nodeIds; nodeIds=nodeIds->nidl_next)
	{
		NodeIdP	nodeId;
		
		nodeId	= nodeIds->nidl_node_id;

		Assert (nodeId != NULL);
		if (nodeId->nid_mark & NID_ALIAS_MASK)
		{
			nodeId	= nodeId->nid_forward_node_id;
			Assert (nodeId != NULL);
		}

		Assert (nodeId != NULL);
		AddRefCount (nodeId);
		Assert (nodeId->nid_ref_count_sign == -1);
	}
} /* BEAddNodeIdsRefCounts */

static NodeIdRefCountListP
CopyRefCountList (NodeIdRefCountListP refCount)
{
	NodeIdRefCountListP	first, copy;

	first	= NULL;
	copy	= NULL;
	for (; refCount != NULL; refCount = refCount->nrcl_next)
	{
		NodeIdP				nodeId;
		NodeIdRefCountListP	new;

		nodeId	= refCount->nrcl_node_id;

		Assert (nodeId->nid_ref_count_sign == -1);

		new	= NewRefCount (NULL, nodeId, refCount->nrcl_ref_count);

		if (copy == NULL)
			first	= new;
		else
			copy->nrcl_next	=	new;

		copy	=	new;
	}

	return (first);
} /* CopyRefCountList */

BENodeP
BESwitchNode (BENodeIdP nodeId, BEArgP cases)
{
	NodeP	switchNode;

	switchNode	= ConvertAllocType (NodeS);
	
	switchNode->node_kind		= SwitchNode;
	switchNode->node_node_id	= nodeId;
	switchNode->node_arity		= 1;
	switchNode->node_arguments	= cases;
	switchNode->node_annotation	= NoAnnot;

	Assert (nodeId->nid_ref_count_sign == -1);
	
	return (switchNode);
} /* BESwitchNode */

void
BEEnterLocalScope (void)
{
	NodeIdRefCountListP	refCount;

	gRefCountList	= CopyRefCountList (gRefCountList);

	for (refCount = gRefCountList; refCount != NULL; refCount = refCount->nrcl_next)
	{
		NodeIdP	nodeId;

		nodeId	= refCount->nrcl_node_id;

		Assert (nodeId->nid_ref_count_sign == -1);

		refCount->nrcl_ref_count	= nodeId->nid_refcount;
		nodeId->nid_refcount		= -1;
	}

	Assert (gCurrentScope < kMaxScope);
	gRefCountLists [gCurrentScope++]	= gRefCountList;
} /* BEEnterLocalScope */

void
BELeaveLocalScope (BENodeP node)
{
	NodeIdRefCountListP	refCount;

	Assert (gCurrentScope > 0);
	gRefCountList	= gRefCountLists [--gCurrentScope];

	for (refCount = gRefCountList; refCount != NULL; refCount = refCount->nrcl_next)
	{
		NodeIdP	nodeId;
		int		count;

		nodeId	= refCount->nrcl_node_id;

		Assert (nodeId->nid_ref_count_sign == -1);

		count	= refCount->nrcl_ref_count;
		refCount->nrcl_ref_count	= nodeId->nid_refcount;
		nodeId->nid_refcount	+= count + 1;
	}

	Assert (node->node_kind == CaseNode || node->node_kind == DefaultNode);
	node->node_node_id_ref_counts	= gRefCountList;
} /* BELeaveLocalScope */

BENodeP
BECaseNode (int symbolArity, BESymbolP symbol, BENodeDefP nodeDefs, BEStrictNodeIdP strictNodeIds, BENodeP node)
{
	NodeP	caseNode;
	
	caseNode	= ConvertAllocType (NodeS);

	caseNode->node_kind			= CaseNode;
	caseNode->node_symbol		= symbol;
	caseNode->node_arity		= symbolArity;
	caseNode->node_node_defs	= nodeDefs;
	caseNode->node_arguments	= NewArgument (node);

	caseNode->node_su.su_u.u_case		= ConvertAllocType (CaseNodeContentsS);
	caseNode->node_node_id_ref_counts	= NULL;
	caseNode->node_strict_node_ids	= strictNodeIds;

	return (caseNode);
} /* BECaseNode */

BENodeP
BEDefaultNode (BENodeDefP nodeDefs, BEStrictNodeIdP strictNodeIds, BENodeP node)
{
	NodeP	defaultNode;
	
	defaultNode	= ConvertAllocType (NodeS);

	defaultNode->node_kind		= DefaultNode;
	defaultNode->node_node_defs	= nodeDefs;
	defaultNode->node_arity		= 1;
	defaultNode->node_arguments	= NewArgument (node);

	defaultNode->node_su.su_u.u_case		= ConvertAllocType (CaseNodeContentsS);
	defaultNode->node_strict_node_ids	= strictNodeIds;
	defaultNode->node_node_id_ref_counts	= NULL;
	
	return (defaultNode);
} /* BEDefaultNode */

BENodeP
BEPushNode (int arity, BESymbolP symbol, BEArgP arguments, BENodeIdListP nodeIds)
{
	NodeP	pushNode;

	pushNode	= ConvertAllocType (NodeS);

	pushNode->node_kind			= PushNode;
	pushNode->node_arity		= arity;
	pushNode->node_arguments	= arguments;
#if STRICT_LISTS
	pushNode->node_push_symbol = symbol;
#else
	pushNode->node_record_symbol= symbol;
#endif
	pushNode->node_node_ids		= nodeIds;
	pushNode->node_number		= 0;
/*
	for (; nodeIds; nodeIds=nodeIds->nidl_next)
	{
		NodeIdP	nodeId;
		
		nodeId	= nodeIds->nidl_node_id;

		Assert (nodeId->nid_ref_count_sign == -1);

		nodeId->nid_refcount++;
	}
*/
	Assert (arguments->arg_node->node_kind == NodeIdNode);
	Assert (arguments->arg_node->node_node_id->nid_ref_count_sign == -1);

	arguments->arg_node->node_node_id->nid_refcount++;
	
	return (pushNode);
} /* BEPushNode */

BENodeP
BESelectorNode (BESelectorKind selectorKind, BESymbolP fieldSymbol, BEArgP args)
{
	NodeP	node;

	Assert (CountArgs (args) == 1);

	node	= ConvertAllocType (NodeS);

	node->node_annotation	= NoAnnot;
	node->node_kind			= SelectorNode;
	node->node_symbol		= fieldSymbol;
	node->node_arity		= selectorKind;
	node->node_arguments	= args;
	node->node_number		= 0;

	return (node);
} /* BESelectorNode */

BENodeP
BEUpdateNode (BEArgP args)
{
	NodeP	node;
	SymbolP	recordSymbol;

	Assert (CountArgs (args) == 2);
	Assert (args->arg_next->arg_node->node_kind == SelectorNode);
	Assert (args->arg_next->arg_node->node_arity == BESelector);

	recordSymbol	= args->arg_next->arg_node->node_symbol->symb_def->sdef_type->type_lhs->ft_symbol;

	node	= ConvertAllocType (NodeS);

	node->node_annotation	= NoAnnot;
	node->node_kind			= UpdateNode;
	node->node_symbol		= recordSymbol;
	node->node_arity		= 2;
	node->node_arguments	= args;
	node->node_number=0;

	return (node);
} /* BEUpdateNode */

BENodeP
BENodeIdNode (BENodeIdP nodeId, BEArgP args)
{
	NodeP	node;

	node	= ConvertAllocType (NodeS);

	node->node_annotation	= NoAnnot;
	node->node_kind			= NodeIdNode;
	node->node_node_id		= nodeId;
	node->node_arity		= CountArgs (args);
	node->node_arguments	= args;
	node->node_number		= 0;

	return (node);
} /* BENodeIdNode */

BEArgP
BENoArgs (void)
{
	return (NULL);
} /* BENoArgs */

BEArgP
BEArgs (BENodeP node, BEArgP nextArgs)
{
	ArgP	arg;

	arg	= ConvertAllocType (ArgS);

	arg->arg_node	= node;
	arg->arg_next	= nextArgs;

	return (arg);
} /* BEArgs */

void
BEDeclareNodeId (int sequenceNumber, int lhsOrRhs, CleanString name)
{
	IdentP	newIdent;
	NodeIdP	newNodeId;

	Assert (sequenceNumber < kMaxNumberOfNodeIds);

	/* +++ ifdef DEBUG */
	if (sequenceNumber>=number_of_node_ids){
		int i;
		
		for (i=number_of_node_ids; i<=sequenceNumber; ++i)
			gCurrentNodeIds[i] = NULL;
		
		number_of_node_ids=sequenceNumber+1;
	}
	/* endif DEBUG */

	Assert (gCurrentNodeIds [sequenceNumber] == NULL);

	/* +++ share idents ??? */
	newIdent	= ConvertAllocType (IdentS);
	newIdent->ident_name	= ConvertCleanString (name);

	newNodeId	= ConvertAllocType (NodeIdS);
	newNodeId->nid_ident	= newIdent;

	newNodeId->nid_node_def			= NULL;
	newNodeId->nid_forward_node_id	= NULL;
	newNodeId->nid_node				= NULL;
	newNodeId->nid_state.state_kind	= 0;
	newNodeId->nid_mark				= 0;
	newNodeId->nid_mark2			= 0;
	newNodeId->nid_ref_count_sign	= lhsOrRhs==BELhsNodeId ? -1 : 1;
	newNodeId->nid_refcount			= 0;
	newNodeId->nid_ref_count_copy	= 0;

	gCurrentNodeIds [sequenceNumber]	= newNodeId;
} /* BEDeclareNodeId */

BENodeIdP
BENodeId (int sequenceNumber)
{
	NodeIdP		nodeId;

	Assert ((unsigned)sequenceNumber < (unsigned)kMaxNumberOfNodeIds);

	/* +++ ifdef DEBUG */
	if (sequenceNumber>=number_of_node_ids){
		int i;
		
		for (i=number_of_node_ids; i<=sequenceNumber; ++i)
			gCurrentNodeIds[i] = NULL;
		
		number_of_node_ids=sequenceNumber+1;
	}
	/* endif DEBUG */

	nodeId	= gCurrentNodeIds [sequenceNumber];

	Assert (nodeId != NULL);

	if (nodeId->nid_mark & NID_ALIAS_MASK)
	{
		nodeId	= nodeId->nid_forward_node_id;
		Assert (nodeId != NULL);
	}

	Assert (nodeId != NULL);

	nodeId->nid_refcount	+= nodeId->nid_ref_count_sign;

	return (nodeId);
} /* BENodeId */

BENodeIdP
BEWildCardNodeId (void)
{
	NodeIdP	newNodeId;

	/* +++ share wild card nodeids ??? */

	newNodeId	= ConvertAllocType (NodeIdS);

	newNodeId->nid_ident			= NULL;
	newNodeId->nid_node_def			= NULL;
	newNodeId->nid_forward_node_id	= NULL;
	newNodeId->nid_node				= NULL;
	newNodeId->nid_state.state_kind	= 0;
	newNodeId->nid_mark				= 0;
	newNodeId->nid_mark2			= 0;
	newNodeId->nid_ref_count_sign	= -1;
	newNodeId->nid_refcount			= -1;

	return (newNodeId);
} /* BEWildCardNodeId */

BENodeDefP
BENodeDef (int sequenceNumber, BENodeP node)
{
	NodeIdP		nodeId;
	NodeDefP	nodeDef;

	Assert ((unsigned)sequenceNumber < (unsigned)kMaxNumberOfNodeIds);

	/* +++ ifdef DEBUG */
	if (sequenceNumber>=number_of_node_ids){
		int i;
		
		for (i=number_of_node_ids; i<=sequenceNumber; ++i)
			gCurrentNodeIds[i] = NULL;
		
		number_of_node_ids=sequenceNumber+1;
	}
	/* endif DEBUG */

	nodeDef	=	ConvertAllocType (NodeDefS);

	nodeId	= gCurrentNodeIds [sequenceNumber];

	Assert (nodeId != NULL);
	Assert (nodeId->nid_node == NULL);
	nodeId->nid_node_def	= nodeDef;
	nodeId->nid_node		= node;

	nodeDef->def_id		= nodeId;
	nodeDef->def_node	= node;
	/* ifdef DEBUG */
	nodeDef->def_next	= NULL;
	/* endif DEBUG */

	return (nodeDef);
} /* BENodeDef */

BENodeDefP
BENodeDefs (BENodeDefP nodeDef, BENodeDefP nodeDefs)
{
	Assert (nodeDef->def_next == NULL);

	nodeDef->def_next	= nodeDefs;

	return (nodeDef);
} /* BENodeDefs */

BENodeDefP
BENoNodeDefs (void)
{
	return (NULL);
} /* BENoNodeDefs */

BEStrictNodeIdP
BEStrictNodeId (BENodeIdP nodeId)
{
	StrictNodeId	strictNodeId;

	strictNodeId	=	ConvertAllocType (struct strict_node_id);
	strictNodeId->snid_mark		= 0;
	strictNodeId->snid_node_id	= nodeId;

	/* +++ remove this hack */
	nodeId->nid_refcount--;

	/* ifdef DEBUG */
	strictNodeId->snid_next	= NULL;
	/* endif */

	return (strictNodeId);
} /* BEStrictNodeId */

BEStrictNodeIdP
BEStrictNodeIds (BEStrictNodeIdP strictNodeId, BEStrictNodeIdP strictNodeIds)
{
	Assert (strictNodeId->snid_next == NULL);

	strictNodeId->snid_next	= strictNodeIds;

	return (strictNodeId);
} /* BEStrictNodeIds */

BEStrictNodeIdP
BENoStrictNodeIds (void)
{
	return (NULL);
} /* BENoStrictNodeIds */

static NodeDefP
CollectNodeNodeDefs (NodeP node, NodeDefP defs)
{
	switch (node->node_kind)
	{
		case NormalNode:
			{
				ArgP	arg;

				for (arg = node->node_arguments; arg != NULL; arg = arg->arg_next)
					defs	= CollectNodeNodeDefs (arg->arg_node, defs);
			}
			break;
		case NodeIdNode:
			{
				NodeIdP	nodeId;
			
				nodeId	= node->node_node_id;
				if (nodeId->nid_node != NULL && !(nodeId->nid_mark & NID_VERIFY_MASK))
				{
					NodeDefP	nodeDef;

					nodeId->nid_mark |= NID_VERIFY_MASK;

					nodeDef	=	ConvertAllocType (NodeDefS);

					nodeDef->def_id		= nodeId;
					nodeDef->def_node	= nodeId->nid_node;
					nodeDef->def_next	= defs;

					nodeId->nid_node_def			= nodeDef;

					defs	= CollectNodeNodeDefs (nodeId->nid_node, nodeDef);
				}
			}
			break;
		default:
			break;
	}

	return (defs);
} /* CollectNodeNodeDefs */

static NodeDefP
CollectNodeDefs (NodeP node, NodeDefP defs)
{
	NodeDefP	def;

	for (def = defs; def != NULL; def = def->def_next)
		def->def_id->nid_mark |= NID_VERIFY_MASK;

	defs	= CollectNodeNodeDefs (node, defs);

	for (def = defs; def != NULL; def = def->def_next)
		def->def_id->nid_mark &= ~NID_VERIFY_MASK;

	return (defs);
} /* CollectNodeDefs */

BERuleAltP
BERuleAlt (int line, BENodeDefP lhsDefs, BENodeP lhs, BENodeDefP rhsDefs, BEStrictNodeIdP rhsStrictNodeIds, BENodeP rhs)
{
	RuleAltP	alt;

	alt	= ConvertAllocType (RuleAltS);

	alt->alt_lhs_root			= lhs;
	alt->alt_lhs_defs 			= CollectNodeDefs (lhs, lhsDefs);
	alt->alt_rhs_root			= rhs;
	alt->alt_rhs_defs 			= rhsDefs;
	alt->alt_line				= line;
	alt->alt_kind				= Contractum;
	alt->alt_strict_node_ids	= rhsStrictNodeIds;

	/* +++ ifdef DEBUG */
	alt->alt_next				= NULL;
	number_of_node_ids=0;
	/* endif DEBUG */

	set_scope_numbers (alt);

	return (alt);
} /* BERuleAlt */

BERuleAltP
BECodeAlt (int line, BENodeDefP lhsDefs, BENodeP lhs, BECodeBlockP codeBlock)
{
	RuleAltP	alt;

	alt	= ConvertAllocType (RuleAltS);

	alt->alt_lhs_root			= lhs;
	alt->alt_lhs_defs 			= CollectNodeDefs (lhs, lhsDefs);
	alt->alt_rhs_code			= codeBlock;
	alt->alt_rhs_defs 			= NULL;
	alt->alt_line				= line;
	alt->alt_kind				= ExternalCall;
	alt->alt_strict_node_ids	= NULL;

	/* +++ ifdef DEBUG */
	alt->alt_next				= NULL;
	number_of_node_ids=0;
	/* endif DEBUG */

# ifdef CODE_INLINE_FLAG
	/* RWS +++ move to code generator ??? */
	if (codeBlock->co_is_abc_code && codeBlock->co_is_inline)
	{
		char			*functionName, *instructionLine;
		Instructions	instruction;

		Assert (lhs->node_kind == NormalNode);
		Assert (lhs->node_symbol->symb_kind == definition);
		functionName	= lhs->node_symbol->symb_def->sdef_ident->ident_name;

		/* .inline <name> */
		instructionLine	= ConvertAlloc (sizeof (".inline ") + strlen (functionName));
		strcpy (instructionLine, ".inline ");
		strcat (instructionLine, functionName);

		instruction	= ConvertAllocType (Instruction);
		instruction->instr_this	= instructionLine;
		instruction->instr_next	= codeBlock->co_instr;
		codeBlock->co_instr	= instruction;

		for (; instruction->instr_next != NULL; instruction = instruction->instr_next)
			/* find last element */;
		instruction	= instruction->instr_next	= ConvertAllocType (Instruction);

		instruction->instr_this	= ".end";
		instruction->instr_next	= NULL;
	}
# endif

	return (alt);
} /* BECodeAlt */


BERuleAltP
BERuleAlts (BERuleAltP alt, BERuleAltP alts)
{
	Assert (alt->alt_next == NULL);

	alt->alt_next	= alts;

	return (alt);
} /* BERuleAlts*/

BERuleAltP
BENoRuleAlts (void)
{
	return (NULL);
} /* BENoRuleAlts */

static void
DeclareFunctionC (char *name, int arity, int functionIndex, unsigned int ancestor)
{
	SymbDefP	newSymbDef;
	Ident		newIdent;
	SymbolP	 	functions;
	BEIcl		icl;
	BEModule	module;

	icl	= &gBEState.be_icl;

	module	= &gBEState.be_modules [main_dcl_module_n];
	functions	=	module->bem_functions;
	Assert (functions != NULL);

	Assert (icl->beicl_previousAncestor <= ancestor);
	icl->beicl_previousAncestor	= ancestor;

	Assert (functionIndex < module->bem_nFunctions);
	newSymbDef	= ConvertAllocType (SymbDefS);

	newSymbDef->sdef_kind		= IMPRULE;
	newSymbDef->sdef_mark		= 0;
	newSymbDef->sdef_over_arity	= 0;
	newSymbDef->sdef_arity		= arity;
	newSymbDef->sdef_module		= module->bem_name;
	newSymbDef->sdef_ancestor	= ancestor;
	newSymbDef->sdef_arfun		= NoArrayFun;
	newSymbDef->sdef_next_scc	= NULL;
	newSymbDef->sdef_exported	= False;
	newSymbDef->sdef_dcl_icl	= NULL;
	newSymbDef->sdef_isused		= 0;
	newSymbDef->sdef_no_sa		= False;

	newSymbDef->sdef_nr_of_lifted_nodeids	= 0;	/* used in PrintType */
	newSymbDef->sdef_line					= 0;	/* used in PrintType */

	*icl->beicl_depsP	= newSymbDef;
	icl->beicl_depsP	= &newSymbDef->sdef_next_scc;
	newSymbDef->sdef_arfun		= NoArrayFun;

	newIdent	= ConvertAllocType (IdentS);

	newIdent->ident_name	= name;
	newIdent->ident_symbol	= &functions [functionIndex];

	newSymbDef->sdef_ident	= newIdent;

	Assert (functions [functionIndex].symb_kind == erroneous_symb);
	functions [functionIndex].symb_kind	= definition;
	functions [functionIndex].symb_def	= newSymbDef;


	/* +++ ugly */
	if (strcmp (newIdent->ident_name, "Start") == 0)
	{
		Assert (icl->beicl_module->im_start == NULL);
		icl->beicl_module->im_start	= newSymbDef;
	}
} /* DeclareFunctionC */

void
BEDeclareFunction (CleanString name, int arity, int functionIndex, int ancestor)
{
	/* +++ ugly */
	if (strncmp (name->chars, "Start;", 6) == 0)
		name->length	= 5;

	DeclareFunctionC (ConvertCleanString (name), arity, functionIndex, ancestor);
} /* BEDeclareFunction */

BEImpRuleP
BERules (BEImpRuleP rule, BEImpRuleP rules)
{
	Assert (rule->rule_next == NULL);

	rule->rule_next	= rules;

	return (rule);
} /* BERules */

BEImpRuleP
BENoRules (void)
{
	return (NULL);
} /* BENoRules */

BEImpRuleP
BERule (int functionIndex, int isCaf, BETypeAltP type, BERuleAltP alts)
{
	SymbDefP	functionDef;
	SymbolP		functionSymbol;
	ImpRuleP	rule;
	BEModule	module;

	rule	= ConvertAllocType (ImpRuleS);

	module	= &gBEState.be_modules [main_dcl_module_n];
	functionSymbol	= &module->bem_functions [functionIndex];
	functionDef	= functionSymbol->symb_def;
	functionDef->sdef_rule	= rule;

	rule->rule_type	= type;
	rule->rule_alts	= alts;
	rule->rule_mark	= isCaf ? RULE_CAF_MASK : 0;

	rule->rule_root	= alts->alt_lhs_root;

	/* ifdef DEBUG */
	rule->rule_next	= NULL;
	/* endif DEBUG */

	return (rule);
} /* BERule */

void
BEDeclareRuleType (int functionIndex, int moduleIndex, CleanString name)
{
	IdentP		newIdent;
	SymbDefP	newSymbDef;
	SymbolP		functions;
	BEModuleP	module;

	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) functionIndex < module->bem_nFunctions);

	functions	= module->bem_functions;

	Assert (functions != NULL);
	Assert (functions [functionIndex].symb_kind == erroneous_symb);

	if (module->bem_isSystemModule)
		/* for inline code */
		newIdent	= PutStringInHashTable (ConvertCleanString (name), SymbolIdTable);
	else
	{
		newIdent	= ConvertAllocType (IdentS);
		newIdent->ident_name	= ConvertCleanString (name);
	}

	newIdent->ident_symbol	= &functions [functionIndex];

	newSymbDef	= ConvertAllocType (SymbDefS);
	newSymbDef->sdef_kind		= NEWDEFINITION;
	newSymbDef->sdef_exported	= False;
	newSymbDef->sdef_module		= module->bem_name;
	newSymbDef->sdef_ident		= newIdent;
	newSymbDef->sdef_isused		= 0;
	newSymbDef->sdef_line		= 0;	/* used in PrintSymbolOfIdent */

	functions [functionIndex].symb_kind	= definition;
	functions [functionIndex].symb_def	= newSymbDef;

} /* BEDeclareRuleType */

void
BEDefineRuleType (int functionIndex, int moduleIndex, BETypeAltP typeAlt)
{
	SymbolP		functionSymbol;
	SymbDef		sdef;
	RuleTypes	ruleType;
	BEModule	module;

	ruleType	= ConvertAllocType (struct rule_type);
	ruleType->rule_type_rule	= typeAlt;

	module	= &gBEState.be_modules [moduleIndex];
	functionSymbol	= &module->bem_functions [functionIndex];

	sdef	= functionSymbol->symb_def;
	Assert (sdef->sdef_kind == NEWDEFINITION);
	sdef->sdef_over_arity	= 0;
	sdef->sdef_arity		= typeAlt->type_alt_lhs->type_node_arity;
	sdef->sdef_arfun		= NoArrayFun;
	sdef->sdef_kind 		= module->bem_isSystemModule ? SYSRULE : DEFRULE;
	sdef->sdef_rule_type	= ruleType;
} /* BEDefineRuleType */

void
BEAdjustArrayFunction (BEArrayFunKind arrayFunKind, int functionIndex, int moduleIndex)
{
	SymbolP		functionSymbol;
	SymbDef		sdef;
	BEModule	module;

	module	= &gBEState.be_modules [moduleIndex];

	functionSymbol	= &module->bem_functions [functionIndex];

	sdef	= functionSymbol->symb_def;

	Assert (sdef->sdef_kind == DEFRULE || (moduleIndex == main_dcl_module_n && sdef->sdef_kind == IMPRULE));
	sdef->sdef_arfun	= arrayFunKind;
	sdef->sdef_mark		= 0;

	if (sdef->sdef_kind == DEFRULE  && moduleIndex == main_dcl_module_n)
	{
		AddUserDefinedArrayFunction (functionSymbol);
		sdef->sdef_kind	= SYSRULE;
	}
} /* BEAdjustArrayFunction */

BETypeP
BETypes (BETypeP type, BETypeP types)
{
	Assert (type->type_next == NULL);

	type->type_next	= types;

	return (type);
} /* BETypes */

BETypeP
BENoTypes (void)
{
	return (NULL);
} /* BENoTypes */

void
BEDeclareType (int typeIndex, int moduleIndex, CleanString name)
{
	SymbDefP	newSymbDef;
	Ident		newIdent;
	SymbolP	 	*types;
	BEModuleP	module;
	module	= &gBEState.be_modules [moduleIndex];

	Assert ((unsigned int) typeIndex < module->bem_nTypes);
	Assert (module->bem_types [typeIndex]->symb_kind == erroneous_symb);

	types	=	module->bem_types;
	Assert (types != NULL);

	newIdent	= ConvertAllocType (IdentS);
	newIdent->ident_name	= ConvertCleanString (name);
	newIdent->ident_symbol	= types [typeIndex];
/* RWS change this
	newSymbDef	= ConvertAllocType (SymbDefS);
*/
	newSymbDef	= types [typeIndex]->symb_def;
	Assert (newSymbDef != NULL);

	newSymbDef->sdef_kind		= NEWDEFINITION;
	newSymbDef->sdef_exported	= False;
	newSymbDef->sdef_dcl_icl	= NULL;
	newSymbDef->sdef_isused		= 0;

	newSymbDef->sdef_module		= module->bem_name;
	newSymbDef->sdef_ident		= newIdent;

	types [typeIndex]->symb_kind	= definition;
	types [typeIndex]->symb_def		= newSymbDef;
} /* BEDeclareType */
 
BETypeVarP
BETypeVar (CleanString name)
{
	IdentP	ident;
	TypeVar	typeVar;

	ident	= ConvertAllocType (IdentS);
	typeVar	= ConvertAllocType (struct type_var);

	ident->ident_name	= ConvertCleanString (name);
	ident->ident_tv	= typeVar;

	typeVar->tv_ident		= ident;
	typeVar->tv_mark		= 0;
	typeVar->tv_argument_nr	= 0; /* ??? */

	return (typeVar);
} /* BETypeVar */

BETypeVarListP
BETypeVars (BETypeVarP typeVar, BETypeVarListP typeVarList)
{
	TypeVarList	typeVarListElement;

	typeVarListElement	= ConvertAllocType (struct type_var_list);
	typeVarListElement->tvl_elem	= typeVar;
	typeVarListElement->tvl_next	= typeVarList;

	return (typeVarListElement);
} /* BETypeVars */

BETypeVarListP
BENoTypeVars (void)
{
	return (NULL);
} /* BENoTypeVars */

BEFlatTypeP
BEFlatType (BESymbolP symbol, BETypeVarListP arguments)
{
	FlatType	flatType;
	int			i;

	flatType	= ConvertAllocType (struct flat_type);

	flatType->ft_symbol		= symbol;
	flatType->ft_arguments	= arguments;
	i	= 0;
	for (; arguments != NULL; arguments=arguments->tvl_next)
		i++;
	flatType->ft_arity	= i;

	flatType->ft_cons_vars	= NULL;	/* used in PrintType */

	return (flatType);
} /* BEFlatType */

void
BEAlgebraicType (BEFlatTypeP lhs, BEConstructorListP constructors)
{
	Types		type;
	SymbDefP	sdef;
	int			nConstructors;

	type	= ConvertAllocType (struct type);
	/* ifdef DEBUG */
	type->type_next	= NULL;
	/* endif */

	type->type_lhs	=	lhs;
	type->type_line	=	0; /* ??? */
	type->type_constructors	= constructors;

	nConstructors	=	0;
	for (; constructors != NULL; constructors = constructors->cl_next)
	{
		SymbDef	cdef;

		Assert (!constructors->cl_constructor->type_node_is_var);
		Assert (constructors->cl_constructor->type_node_symbol->symb_kind == definition);

		cdef	= constructors->cl_constructor->type_node_symbol->symb_def;
		Assert (cdef->sdef_type == NULL);
		cdef->sdef_type	= type;

		nConstructors++;
	}

	type->type_nr_of_constructors	= nConstructors;

	Assert (type->type_lhs->ft_symbol->symb_kind == definition);
	sdef	= type->type_lhs->ft_symbol->symb_def;
	Assert (sdef->sdef_kind == NEWDEFINITION);
	sdef->sdef_over_arity	= 0;
	sdef->sdef_kind 		= TYPE;
	sdef->sdef_type			= type;
} /* BEAlgebraicType */

void
BERecordType (int moduleIndex, BEFlatTypeP lhs, BETypeNodeP constructorType, BEFieldListP fields)
{
	int					nFields;
	Types				type;
	SymbDefP			sdef;
	BEConstructorListP	constructor;

	type	= ConvertAllocType (struct type);
	/* ifdef DEBUG */
	type->type_next	= NULL;
	/* endif */

	constructor	= ConvertAllocType (struct constructor_list);

	constructor->cl_next		= NULL;
	constructor->cl_constructor	= constructorType;

	type->type_lhs	=	lhs;
	type->type_line	=	0; /* ??? */
	type->type_constructors	= constructor;
	type->type_fields		= fields;

	nFields	=	0;
	for (; fields != NULL; fields = fields->fl_next)
	{
		SymbDef	fdef;

		Assert (fields->fl_symbol->symb_kind == definition);

		fdef	= fields->fl_symbol->symb_def;
		Assert (fdef->sdef_type == NULL);
		fdef->sdef_type	= type;
		fdef->sdef_sel_field_number	= nFields++;
	}

	type->type_nr_of_constructors	= 0;

	Assert (type->type_lhs->ft_symbol->symb_kind == definition);
	sdef	= type->type_lhs->ft_symbol->symb_def;
	Assert (sdef->sdef_kind == NEWDEFINITION);
	sdef->sdef_over_arity	= 0;
	sdef->sdef_cons_arity	= constructorType->type_node_arity;
	sdef->sdef_checkstatus	= TypeChecked;
	sdef->sdef_kind 		= RECORDTYPE;
	sdef->sdef_type			= type;
	sdef->sdef_arity		= constructorType->type_node_arity;

	// +++ change this
	{
		int	i;
		BEModuleP	module;

		module	= &gBEState.be_modules [moduleIndex];

		for (i = 0; i < module->bem_nConstructors; i++)
			if (module->bem_constructors [i] == constructorType->type_node_symbol)
				break;

		Assert (i < module->bem_nConstructors);
		module->bem_constructors [i]	= type->type_lhs->ft_symbol;
	}
} /* BERecordType */

void
BEAbsType (BEFlatTypeP lhs)
{
	AbsTypes	absType;
	SymbDefP	sdef;

	absType	= ConvertAllocType (struct abs_type);
	/* ifdef DEBUG */
	absType->abs_next	= NULL;
	/* endif */

	absType->abs_graph	=	lhs;
	absType->abs_line	=	0; /* ??? */

	Assert (lhs->ft_symbol->symb_kind == definition);
	sdef	= lhs->ft_symbol->symb_def;
	Assert (sdef->sdef_kind == NEWDEFINITION);
	sdef->sdef_over_arity	= 0;
	sdef->sdef_checkstatus	= TypeChecked;
	sdef->sdef_kind 		= ABSTYPE;
	sdef->sdef_abs_type		= absType;

} /* BEAbsType */

BEConstructorListP
BEConstructors (BEConstructorListP constructor, BEConstructorListP constructors)
{
	Assert (constructor->cl_next == NULL);

	constructor->cl_next	= constructors;

	return (constructor);
} /* BEConstructors */

BEConstructorListP
BENoConstructors (void)
{
	return (NULL);
} /* BENoConstructors */

BEConstructorListP
BEConstructor (BETypeNodeP type)
{
	ConstructorList	constructor;
	SymbDef			sdef;

	Assert (!type->type_node_is_var);
	Assert (type->type_node_symbol->symb_kind == definition);

	sdef	= type->type_node_symbol->symb_def;

	constructor	= ConvertAllocType (struct constructor_list);

	/* ifdef DEBUG */
	constructor->cl_next	= NULL;
	/* endif */
	constructor->cl_constructor	= type;

	sdef->sdef_kind = CONSTRUCTOR;
	sdef->sdef_constructor	= constructor;
	sdef->sdef_arity		= type->type_node_arity;
	sdef->sdef_over_arity	= 0;
	/* ifdef DEBUG */
	sdef->sdef_type			= NULL;
	/* endif */

	return (constructor);
} /* BEConstructor */

void
BEDeclareField (int fieldIndex, int moduleIndex, CleanString name)
{
	SymbDefP	newSymbDef;
	Ident		newIdent;
	SymbolP	 	fields;
	BEModuleP	module;

	module	= &gBEState.be_modules [moduleIndex];
	Assert ((unsigned) fieldIndex < module->bem_nFields);
	Assert (module->bem_fields [fieldIndex].symb_kind == erroneous_symb);

	fields	=	module->bem_fields;
	Assert (fields != NULL);

	newIdent	= ConvertAllocType (IdentS);
	newIdent->ident_name	= ConvertCleanString (name);
	newIdent->ident_symbol	= &fields [fieldIndex];

	newSymbDef	= ConvertAllocType (SymbDefS);
	newSymbDef->sdef_kind		= NEWDEFINITION;
	newSymbDef->sdef_exported	= False;
	newSymbDef->sdef_module		= module->bem_name;
	newSymbDef->sdef_ident		= newIdent;
	newSymbDef->sdef_isused		= 0;

	fields [fieldIndex].symb_kind	= definition;
	fields [fieldIndex].symb_def	= newSymbDef;
} /* BEDeclareField */

BEFieldListP
BEField (int fieldIndex, int moduleIndex, BETypeNodeP type)
{
	SymbDef		sdef;
	SymbolP		fields;
	BEModuleP	module;
	FieldList	field;

	module	= &gBEState.be_modules [moduleIndex];
	Assert ((unsigned) fieldIndex < module->bem_nFields);
	Assert (module->bem_fields [fieldIndex].symb_kind == definition);

	fields	=	module->bem_fields;
	Assert (fields != NULL);

	field	= ConvertAllocType (struct field_list);

	/* ifdef DEBUG */
	field->fl_next	= NULL;
	/* endif */
	field->fl_symbol	= &fields [fieldIndex];
	field->fl_type		= type;

	sdef	=	fields [fieldIndex].symb_def;

	sdef->sdef_kind = FIELDSELECTOR;
	sdef->sdef_sel_field	= field;
	sdef->sdef_arity		= 1;
	sdef->sdef_over_arity	= 0;
	sdef->sdef_mark			= 0;
	/* ifdef DEBUG */
	sdef->sdef_type			= NULL;
	/* endif */

	return (field);
} /* BEField */

BEFieldListP
BEFields (BEFieldListP field, BEFieldListP fields)
{
	Assert (field->fl_next == NULL);

	field->fl_next	= fields;

	return (field);
} /* BEFields */

BEFieldListP
BENoFields (void)
{
	return (NULL);
} /* BENoFields */

void
BEDeclareConstructor (int constructorIndex, int moduleIndex, CleanString name)
{
	SymbDefP	newSymbDef;
	Ident		newIdent;
	SymbolP	 	*constructors;
	BEModuleP	module;

	module	= &gBEState.be_modules [moduleIndex];
	Assert ((unsigned) constructorIndex < module->bem_nConstructors);
	Assert (module->bem_constructors [constructorIndex]->symb_kind == erroneous_symb);

	constructors	=	module->bem_constructors;
	Assert (constructors != NULL);

	newIdent	= ConvertAllocType (IdentS);
	newIdent->ident_name	= ConvertCleanString (name);
	newIdent->ident_symbol	= constructors [constructorIndex];

	newSymbDef	= ConvertAllocType (SymbDefS);
	newSymbDef->sdef_kind		= NEWDEFINITION;
	newSymbDef->sdef_exported	= False;
	newSymbDef->sdef_module		= module->bem_name;
	newSymbDef->sdef_ident		= newIdent;
	newSymbDef->sdef_isused		= 0;
	newSymbDef->sdef_no_sa		= False;

	constructors [constructorIndex]->symb_kind	= definition;
	constructors [constructorIndex]->symb_def	= newSymbDef;
} /* BEDeclareConstructor */

void
BEDefineRules (BEImpRuleP rules)
{
	gBEState.be_icl.beicl_module->im_rules	= rules;
} /* BEDefineRules */

void
BEDefineImportedObjsAndLibs (BEStringListP objs, BEStringListP libs)
{
	gBEState.be_icl.beicl_module->im_imported_objs	= objs;
	gBEState.be_icl.beicl_module->im_imported_libs	= libs;
} /* BEDefineRules */

BEStringListP
BEString (CleanString cleanString)
{
	struct string_list	*string;

	string	= ConvertAllocType (struct string_list);

	string->sl_string	= ConvertCleanString (cleanString);
	/* ifdef DEBUG */
	string->sl_next	= NULL;
	/* endif */

	return (string);
} /* BEString */

BEStringListP
BEStrings (BEStringListP string, BEStringListP strings)
{
	Assert (string->sl_next == NULL);

	string->sl_next	= strings;

	return (string);
} /* BEStringList*/

BEStringListP
BENoStrings (void)
{
	return (NULL);
} /* BENoStrings */


BENodeIdListP
BENodeIdListElem (BENodeIdP nodeId)
{
	struct node_id_list_element	*elem;

	elem	= ConvertAllocType (struct node_id_list_element);

	elem->nidl_node_id	= nodeId;
	/* ifdef DEBUG */
	elem->nidl_next	= NULL;
	/* endif */

	return (elem);
} /* BENodeIdListElem */

BENodeIdListP
BENodeIds (BENodeIdListP nid, BENodeIdListP nids)
{
	Assert (nid->nidl_next == NULL);

	nid->nidl_next	= nids;

	return (nid);
} /* BENodeIds*/

BENodeIdListP
BENoNodeIds (void)
{
	return (NULL);
} /* BENoNodeIds */

BECodeBlockP
BEAbcCodeBlock (int inlineFlag, BEStringListP instructions)
{
	CodeBlock	codeBlock;

	codeBlock	=	ConvertAllocType (CodeBlockS);

	codeBlock->co_instr			= (Instructions) instructions;
	codeBlock->co_is_abc_code	= True;
	codeBlock->co_is_inline		= inlineFlag;

	return (codeBlock);
} /* BEAbcCodeBlock */

BECodeBlockP
BEAnyCodeBlock (BECodeParameterP inParams, BECodeParameterP outParams, BEStringListP instructions)
{
	CodeBlock	codeBlock;

	codeBlock	=	ConvertAllocType (CodeBlockS);

	codeBlock->co_instr			= (Instructions) instructions;
	codeBlock->co_is_abc_code	= False;
	codeBlock->co_parin			= inParams;
	codeBlock->co_parout		= outParams;

	return (codeBlock);
} /* BEAnyCodeBlock */

BECodeParameterP
BECodeParameter (CleanString location, BENodeIdP nodeId)
{
	Parameters	parameter;

	parameter	= ConvertAllocType (struct parameter);

	parameter->par_kind		= 0;
	parameter->par_node_id	= nodeId;
	parameter->par_loc		= Identifier (ConvertCleanString (location));

	/* ifdef DEBUG */
	parameter->par_next	= NULL;
	/* endif */

	return (parameter);
} /* BECodeParameter */

BECodeParameterP
BECodeParameters (BECodeParameterP parameter, BECodeParameterP parameters)
{
	Assert (parameter->par_next == NULL);

	parameter->par_next	= parameters;

	return (parameter);
} /* BECodeParameters */

BECodeParameterP
BENoCodeParameters (void)
{
	return (NULL);
} /* BENoCodeParameters */

static void
RemoveSpecialArrayFunctionsFromSymbolList (SymbolP *symbolH)
{
	SymbolP	symbolP;

	while ((symbolP = *symbolH) != NULL)
	{
		SymbDefP	sdef;

		sdef	= symbolP->symb_def;

		if (symbolP->symb_kind == definition && sdef->sdef_kind == IMPRULE && sdef->sdef_arfun != NoArrayFun)
			*symbolH	= symbolP->symb_next;
		else
			symbolH	= &symbolP->symb_next;
	}
} /* RemoveSpecialArrayFunctionsFromSymbolList */

int
BEGenerateCode (CleanString outputFile)
{
	char	*outputFileName;
	ImpRule	rule;

	if (CompilerError)
		return False;

	// RemoveSpecialArrayFunctionsFromSymbolList (&gBEState.be_icl.beicl_module->im_symbols);

	/* +++ hack */
	rule	= gBEState.be_dictionarySelectFunSymbol->symb_def->sdef_rule;
	rule->rule_next	= gBEState.be_icl.beicl_module->im_rules;
	gBEState.be_icl.beicl_module->im_rules	=	rule;

	rule	= gBEState.be_dictionaryUpdateFunSymbol->symb_def->sdef_rule;
	rule->rule_next	= gBEState.be_icl.beicl_module->im_rules;
	gBEState.be_icl.beicl_module->im_rules	=	rule;

	outputFileName	= ConvertCleanString (outputFile);

#if 0
	{
		File f;
		
		f=fopen ("Rules","w");
		if (f){
			ImpRuleS *rule;

			for (rule=gBEState.be_icl.beicl_module->im_rules; rule!=NULL; rule=rule->rule_next){
				PrintImpRule (rule,4,f);
				
				if (rule->rule_next!=NULL)
					FPutC ('\n',f);
			}
			fclose (f);
		}
	}
#endif

	CodeGeneration (gBEState.be_icl.beicl_module, outputFileName);

	return (!CompilerError);
} /* BEGenerateCode */

void
BEExportType (int dclTypeIndex, int iclTypeIndex)
{
	BEModuleP	dclModule, iclModule;
	SymbolP		typeSymbol;
	SymbDefP	iclDef, dclDef;

	iclModule	= &gBEState.be_modules [main_dcl_module_n];

	Assert ((unsigned int) iclTypeIndex < iclModule->bem_nTypes);
	typeSymbol	= iclModule->bem_types [iclTypeIndex];
	Assert (typeSymbol->symb_kind == definition);

	iclDef	= typeSymbol->symb_def;
	iclDef->sdef_exported	= True;

	dclModule	= &gBEState.be_icl.beicl_dcl_module;

	/* +++ remove -1 hack */
	if (dclTypeIndex == -1)
		dclDef	= iclDef;
	else
	{
		Assert ((unsigned int) dclTypeIndex < dclModule->bem_nTypes);
		typeSymbol	= dclModule->bem_types [dclTypeIndex];
		Assert (typeSymbol->symb_kind == definition);
		dclDef	= typeSymbol->symb_def;
	}
	Assert (strcmp (iclDef->sdef_ident->ident_name, dclDef->sdef_ident->ident_name) == 0);

	iclDef->sdef_dcl_icl	= dclDef;
	dclDef->sdef_dcl_icl	= iclDef;
} /* BEExportType */

void
BESwapTypes (int frm, int to)
{
	BEModuleP	module;
	SymbolP		save;

	module	= &gBEState.be_modules [main_dcl_module_n];

	Assert ((unsigned int) frm < module->bem_nTypes);
	Assert ((unsigned int) to < module->bem_nTypes);

	save					= module->bem_types [frm];
	module->bem_types [frm]	= module->bem_types [to];
	module->bem_types [to]	= save;
} /* BESwapTypes */

void
BEExportConstructor (int dclConstructorIndex, int iclConstructorIndex)
{
	BEModuleP	dclModule, iclModule;
	SymbolP		constructorSymbol;
	SymbDefP	iclDef, dclDef;

	iclModule	= &gBEState.be_modules [main_dcl_module_n];

	Assert ((unsigned int) iclConstructorIndex < iclModule->bem_nConstructors);
	constructorSymbol	= iclModule->bem_constructors [iclConstructorIndex];
	Assert (constructorSymbol->symb_kind == definition);

	iclDef	= constructorSymbol->symb_def;
	iclDef->sdef_exported	= True;

	if (0)
	{
		dclModule	= &gBEState.be_icl.beicl_dcl_module;
	
		Assert ((unsigned int) dclConstructorIndex < dclModule->bem_nConstructors);
		constructorSymbol	= dclModule->bem_constructors [dclConstructorIndex];
		Assert (constructorSymbol->symb_kind == definition);
		dclDef	= constructorSymbol->symb_def;
	
		Assert (strcmp (iclDef->sdef_ident->ident_name, dclDef->sdef_ident->ident_name) == 0);
	}
	else
		dclDef	= iclDef;

	iclDef->sdef_dcl_icl	= dclDef;
	dclDef->sdef_dcl_icl	= iclDef;
} /* BEExportConstructor */

void
BEExportField (int dclFieldIndex, int iclFieldIndex)
{
	BEModuleP	dclModule, iclModule;
	SymbolP		fieldSymbol;
	SymbDefP	iclDef, dclDef;

	iclModule	= &gBEState.be_modules [main_dcl_module_n];

	Assert ((unsigned int) iclFieldIndex < iclModule->bem_nFields);
	fieldSymbol	= &iclModule->bem_fields [iclFieldIndex];
	Assert (fieldSymbol->symb_kind == definition);

	iclDef	= fieldSymbol->symb_def;
	iclDef->sdef_exported	= True;

	/* +++ remove -1 hack */
	if (dclFieldIndex == -1)
		dclDef	= iclDef;
	else
	{
		dclModule	= &gBEState.be_icl.beicl_dcl_module;
	
		Assert ((unsigned int) dclFieldIndex < dclModule->bem_nFields);
		fieldSymbol	= &dclModule->bem_fields [dclFieldIndex];
		Assert (fieldSymbol->symb_kind == definition);
		dclDef	= fieldSymbol->symb_def;
	}

	Assert (strcmp (iclDef->sdef_ident->ident_name, dclDef->sdef_ident->ident_name) == 0);

	iclDef->sdef_dcl_icl	= dclDef;
	dclDef->sdef_dcl_icl	= iclDef;
} /* BEExportField */

void
BEExportFunction (int dclFunctionIndex, int iclFunctionIndex)
{
	BEModuleP	dclModule, iclModule;
	SymbolP		functionSymbol;
	SymbDefP	iclDef, dclDef;

	iclModule	= &gBEState.be_modules [main_dcl_module_n];

	Assert ((unsigned int) iclFunctionIndex < iclModule->bem_nFunctions);
	functionSymbol	= &iclModule->bem_functions [iclFunctionIndex];
	Assert (functionSymbol->symb_kind == definition);

	iclDef	= functionSymbol->symb_def;
	iclDef->sdef_exported	= True;

	dclModule	= &gBEState.be_icl.beicl_dcl_module;

	Assert ((unsigned int) dclFunctionIndex < dclModule->bem_nFunctions);
	functionSymbol	= &dclModule->bem_functions [dclFunctionIndex];
	Assert (functionSymbol->symb_kind == definition);
	dclDef	= functionSymbol->symb_def;

	Assert (strcmp (iclDef->sdef_ident->ident_name, dclDef->sdef_ident->ident_name) == 0);

	iclDef->sdef_dcl_icl	= dclDef;
	dclDef->sdef_dcl_icl	= iclDef;
} /* BEExportFunction */

static void
CheckBEEnumTypes (void)
{
	/* Annotation */
 	Assert (NoAnnot		== BENoAnnot);
	Assert (StrictAnnot	== BEStrictAnnot);

	/* Annotation */
 	Assert (NoUniAttr			== BENoUniAttr);
 	Assert (NotUniqueAttr		== BENotUniqueAttr);
 	Assert (UniqueAttr			== BEUniqueAttr);
 	Assert (ExistsAttr			== BEExistsAttr);
 	Assert (UniqueVariable		== BEUniqueVariable);
 	Assert (FirstUniVarNumber	== BEFirstUniVarNumber);

	/* SymbKind */
	Assert (int_type					== BEIntType);
	Assert (bool_type					== BEBoolType);
	Assert (char_type					== BECharType);
	Assert (real_type					== BERealType);
	Assert (file_type					== BEFileType);
	Assert (string_type					== BEStringType);
	Assert (world_type					== BEWorldType);
	Assert (procid_type					== BEProcIdType);
	Assert (redid_type					== BERedIdType);
	Assert (Nr_Of_Basic_Types			== BENrOfBasicTypes);
	Assert (int_denot					== BEIntDenot);
	Assert (bool_denot					== BEBoolDenot);
	Assert (char_denot					== BECharDenot);
	Assert (real_denot					== BERealDenot);
	Assert (Nr_Of_Basic_Denots			== BENrOfBasicDenots);
	Assert (string_denot				== BEStringDenot);
	Assert (fun_type					== BEFunType);
	Assert (array_type					== BEArrayType);
	Assert (strict_array_type			== BEStrictArrayType);
	Assert (unboxed_array_type			== BEUnboxedArrayType);
	Assert (list_type					== BEListType);
	Assert (tuple_type					== BETupleType);
	Assert (empty_type					== BEEmptyType);
#if DYNAMIC_TYPE
	Assert (dynamic_type				== BEDynamicType);
#endif
	Assert (Nr_Of_Predef_Types			== BENrOfPredefTypes);
	Assert (tuple_symb					== BETupleSymb);
	Assert (cons_symb					== BEConsSymb);
	Assert (nil_symb					== BENilSymb);
	Assert (apply_symb					== BEApplySymb);
	Assert (if_symb						== BEIfSymb);
	Assert (fail_symb					== BEFailSymb);
	Assert (all_symb					== BEAllSymb);
	Assert (select_symb					== BESelectSymb);
	Assert (Nr_Of_Predef_FunsOrConses	== BENrOfPredefFunsOrConses);
	Assert (definition					== BEDefinition);
	Assert (newsymbol					== BENewSymbol);
	Assert (instance_symb				== BEInstanceSymb);
	Assert (empty_symbol				== BEEmptySymbol);
	Assert (field_symbol_list			== BEFieldSymbolList);
	Assert (erroneous_symb				== BEErroneousSymb);

	/* ArrayFunKind */
	Assert (CreateArrayFun			== BECreateArrayFun);
	Assert (ArraySelectFun			== BEArraySelectFun);
	Assert (UnqArraySelectFun		== BEUnqArraySelectFun);
	Assert (ArrayUpdateFun			== BEArrayUpdateFun);
	Assert (ArrayReplaceFun			== BEArrayReplaceFun);
	Assert (ArraySizeFun			== BEArraySizeFun);
	Assert (UnqArraySizeFun			== BEUnqArraySizeFun);
	Assert (_CreateArrayFun			== BE_CreateArrayFun);
	Assert (_UnqArraySelectFun		== BE_UnqArraySelectFun);
	Assert (_UnqArraySelectNextFun	== BE_UnqArraySelectNextFun);
	Assert (_UnqArraySelectLastFun	== BE_UnqArraySelectLastFun);
	Assert (_ArrayUpdateFun			== BE_ArrayUpdateFun);
	Assert (NoArrayFun				== BENoArrayFun);

	/* SelectorKind */
	Assert (1			== BESelector);
	Assert (SELECTOR_U	== BESelector_U);
	Assert (SELECTOR_F	== BESelector_F);
	Assert (SELECTOR_L	== BESelector_L);
	Assert (SELECTOR_N	== BESelector_N);
} /* CheckBEEnumTypes */

void
BEArg (CleanString arg)
{
	Assert (gBEState.be_argi < gBEState.be_argc);

	gBEState.be_argv [gBEState.be_argi++]	= ConvertCleanString (arg);

	// +++ ugly
	if (gBEState.be_argi == gBEState.be_argc)
	{
		char	*dummy;
		extern	Bool ParseCommandArgs (int argc, char **argv, char **file_name_p, char **output_file_name_p);

		if (!ParseCommandArgs (gBEState.be_argc, gBEState.be_argv, &dummy, &dummy))
			FatalCompError ("backend", "BEInit", "compilation aborted");

	/*	FatalCompError ("backend", "BEInit", "FatalCompError in backend"); */
	/*	ErrorInCompiler ("backend", "BEInit", "ErrorInCompiler in backend"); */
	/*	StaticMessage (True, "<backend>", "StaticMessage (True) in backend"); */
	/*	StaticMessage (False, "<backend>", "StaticMessage (False) in backend"); */
	/*	*(int*)0L= 17; */
	}
} /* BEArg */

#if STRICT_LISTS
static void init_unboxed_list_symbols (void)
{
	StateP array_state_p,strict_array_state_p,unboxed_array_state_p;
	int i;
	
	for (i=0; i<Nr_Of_Predef_Types; ++i){
		SymbolP symbol_p;
		
		symbol_p=&unboxed_list_symbols[i][0];
		symbol_p->symb_kind=cons_symb;
		symbol_p->symb_head_strictness=4;
		symbol_p->symb_tail_strictness=0;
		symbol_p->symb_state_p=&BasicSymbolStates[i];
		symbol_p->symb_next=NULL;
		
		symbol_p=&unboxed_list_symbols[i][1];
		symbol_p->symb_kind=cons_symb;
		symbol_p->symb_head_strictness=4;
		symbol_p->symb_tail_strictness=1;
		symbol_p->symb_state_p=&BasicSymbolStates[i];
		symbol_p->symb_next=NULL;
	}

	array_state_p=ConvertAllocType (StateS);
	array_state_p->state_type = ArrayState;
	array_state_p->state_arity = 1;
	array_state_p->state_array_arguments = ConvertAllocType (StateS);
	array_state_p->state_mark = 0;
	SetUnaryState (&array_state_p->state_array_arguments[0],OnA,UnknownObj);

	unboxed_list_symbols[array_type][0].symb_state_p=array_state_p;
	unboxed_list_symbols[array_type][1].symb_state_p=array_state_p;

	strict_array_state_p=ConvertAllocType (StateS);
	strict_array_state_p->state_type = ArrayState;
	strict_array_state_p->state_arity = 1;
	strict_array_state_p->state_array_arguments = ConvertAllocType (StateS);
	strict_array_state_p->state_mark = 0;
	strict_array_state_p->state_array_arguments[0] = StrictState;

	unboxed_list_symbols[strict_array_type][0].symb_state_p=strict_array_state_p;
	unboxed_list_symbols[strict_array_type][1].symb_state_p=strict_array_state_p;

	unboxed_array_state_p=ConvertAllocType (StateS);
	unboxed_array_state_p->state_type = ArrayState;
	unboxed_array_state_p->state_arity = 1;
	unboxed_array_state_p->state_array_arguments = ConvertAllocType (StateS);
	unboxed_array_state_p->state_mark = STATE_UNBOXED_ARRAY_MASK;
	unboxed_array_state_p->state_array_arguments [0] = StrictState;

	unboxed_list_symbols[unboxed_array_type][0].symb_state_p=unboxed_array_state_p;
	unboxed_list_symbols[unboxed_array_type][1].symb_state_p=unboxed_array_state_p;
}
#endif

BackEnd
BEInit (int argc)
{
	Assert (!gBEState.be_initialised);

	CurrentPhase	= "Back End";
	CurrentModule	= "<unknown module>";
	CurrentExt		= "";

	InitStorage ();
	/* +++ remove symbol table from backend */
	ScanInitIdentStringTable ();
	InitScanner (); /* for inlining */
	DeltaBId	= Identifier ("StdBool");
	ApplyId		= Identifier ("AP");
	ListId		= Identifier ("List");
	TupleId		= Identifier ("Tuple");
	ConsId		= Identifier ("[:]");
	NilId		= Identifier ("[]");
	SelectId	= Identifier ("_Select");
	IfId		= Identifier ("if");
	FailId		= Identifier ("_Fail");
#if DYNAMIC_TYPE
	DynamicId	= Identifier ("Dynamic");
#endif

	UserDefinedArrayFunctions	= NULL;
#if STRICT_LISTS
	unboxed_record_cons_list=NULL;
	unboxed_record_decons_list=NULL;
#endif

	InitPredefinedSymbols ();

	ClearOpenDefinitionModules ();

	InitARC_Info ();
	InitStatesGen ();
	InitCoding ();
	InitInstructions ();

#if STRICT_LISTS
	init_unboxed_list_symbols();
#endif

	CheckBEEnumTypes ();

	gBEState.be_argv		= ConvertAlloc ((argc+1) * sizeof (char *));
	gBEState.be_argv [argc]	= NULL;
	gBEState.be_argc		= argc;
	gBEState.be_argi		= 0;

	gBEState.be_modules						= NULL;
	gBEState.be_allSymbols					= NULL;
	gBEState.be_dontCareSymbol				= NULL;
	gBEState.be_dictionarySelectFunSymbol	= NULL;
	gBEState.be_dictionaryUpdateFunSymbol	= NULL;

	gBEState.be_initialised	= True;

	return ((BackEnd) &gBEState);
} /* BEInit */

void
BEFree (BackEnd backEnd)
{
	Assert (backEnd == (BackEnd) &gBEState);

	FreeConvertBuffers ();
	CompFree ();

	Assert (gBEState.be_initialised);
	gBEState.be_initialised	= False;

	if (StdErrorReopened)
		fclose (StdError);
	if (StdOutReopened)
		fclose (StdOut);
} /* BEFree */

// temporary hack

void
BEDeclareDynamicTypeSymbol (int typeIndex, int moduleIndex)
{
	gBEState.be_dynamicTypeIndex	= moduleIndex;
	gBEState.be_dynamicModuleIndex	= typeIndex;
} /* BEDeclareDynamicTypeSymbol */


BESymbolP
BEDynamicTempTypeSymbol (void)
{
	return (BETypeSymbol (gBEState.be_dynamicTypeIndex, gBEState.be_dynamicModuleIndex));
} /* BEDynamicTemp */