###############################################################################
#
#	File:     build_symtab.icn
#
#	Subject:  russell language support procedures
#
#	Author:   Dennis J Darland
#
#	Date:     October - Novmber, 2015
#
###############################################################################
#
# Copyright 1986-1989 Hans-Juergen Boehm, Alan J. Demers, Kumar Srikantan,
# Vernon Lee, and Lucy Hederman.
# Copyright Digital Equipment Corporation & INRIA 1988, 1989.
# Copyright (c) 1990-1993 by Xerox Corporation.  All rights reserved.
#
# This material is provided as is, with no warranty expressed or implied.
# Any use is at your own risk.
# 
# Permission is hereby granted to copy this compiler for any non-commercial
# purpose, provided the above notices are retained on all copies.  Further
# restrictions apply to the DEC/INRIA BigNum package.  These are stated in
# the file runtime/BigNum/doc/bnbody.tex.
#
# This work uses the BigNum package developed jointly by INRIA and
# Digital PRL.  It has been modified by Hans-J. Boehm in August 1990
# and February 1993 at Xerox PARC.  When you receive this software,
# please send mail to librarian@prl.dec.com to inform them that you
# have a copy of the package.
###############################################################################
#
#   NOTE From Dennis J. Darland (11/2/2015)
#
#   I obtained the "c" language source code for "russell" copyrighted above
#   in the 1990's. I have made efforts to get it to work over the years, but
#   always failed. It has many hardware and OS dependancies. Now (October 2015
#   forward, I am tring to port to the language "Unicon". Practically every
#   line of code will need to be changed, as someing as simple as the
#   assignment operator is different. Also I will not use the BigNum package
#   mentioned above. Also I am doing this not for profit, and am sharing
#   freely. I am not at all confident that I will get it working well, but
#   believe in open source, so am sharing my work as I make progress.
#   Unicon is also much more portable.
#
###############################################################################


$include "defs.icn"
$include "global_vars.icn"

#
#  Insert the links comprising the symbol table into the syntax tree.
#
# HEREHERE
procedure build_symtab(x_orig)
    local temp, v
    write(sym2file,"Top build symtab")
    if /x_orig  then 
	{
	    write(sym2file,"x_orig = NIL")
	    # Ignore missing clauses. 
	    return nil
	}
    x := fix_p(x_orig)
    write(sym2file,"x  = ")
    if (\ x) then x.dump(sym2file)
    else write(sym2file,"x  = NIL")
    write(stderr,"build_symtab x . kind = " || x.kind)

    case ( x . kind ) of { 
	LISTHEADER: 
			      {
				  # Process every element on the list.
				  temp := x.lh_first
				  while \temp do 
				      {
					  v := temp.cn_hd_field
					  build_symtab(v)
					  temp := temp.cn_tl_field
				      }
			      }
	DECLARATION:
	    {
		# Only for program body declaration. 
		# Add id to symtab. 
                add_id::add_id(x, x)
		# Process program body. Leave decl_block pointing to NIL. 
                build_symtab(x.decl_denotation)
	    }
	PARAMETER: 
	    {
		# Should never get here. 
		bs_error(x)
	    }
	RECORDELEMENT:
	    {
		# Should never get here. 
		bs_error(x)
	    }
	VARSIGNATURE:
	    {
		# Process denotation. 
		build_symtab(x.var_denotation)
	    }
	VALSIGNATURE:
	    {
		# Process denotation. 
		build_symtab(x.val_denotation)
	    }
	FUNCSIGNATURE:
	    {
		# Add the parameter identifiers to symtab.
		
		temp := x.fsig_param_list.lh_first
		while \temp do 
		    {
			v := temp.cn_hd_field
			add_id::add_id(v,x)
			temp := temp.cn_tl_field
		    }
		# Process the parameter signatures and the function 
		# result signature. 
		temp := x.fsig_param_list.lh_first
		while \temp do 
		    {
			v := temp.cn_hd_field
			build_symtab(v.par_signature)
			temp := temp.cn_tl_field
		    }
		build_symtab(x.fsig_result_sig)
		
		# Restore surrounding scope.
		
		temp := x.fsig_param_list.lh_first
		while \temp do 
		    {
			v := temp.cn_hd_field
			restore(v)
			temp := temp.cn_tl_field
		    }
	    }
	TYPESIGNATURE:
	    {
		# Add local id to symtab. 
                add_id::add_id(x, x)
                # push(x,lti_stack)
		# Process each component signature.
		temp := x.ts_clist.lh_first
		while \temp do 
		    {
			case (v.kind) of {
			    TSCOMPONENT:
				{
				    # v . tsc_id . id_last_definition = NIL; 
				    build_symtab(v.tsc_signature)
				}
			    DEFCHARSIGS: 
				{
				}
			    # Ignore. 
			    default:
				{
				    bs_error(v)
				}
			} 
		    }
		
		# Restore surrounding scope. 
                restore(x)
                # pop(lti_stack) 
	    }
	TSCOMPONENT:
	    {
		# Should never get here. 
		bs_error(x)
	    }
	BLOCKDENOTATION: 
	    {
		# Add declaration identifiers to symtab. 
		write(sym2file,"BLOCKDENOTATION x.bld_declaration_list = " || dump_info(x.bld_declaration_list))
		temp := x.bld_declaration_list.lh_first
		write(sym2file,"BLOCKDENOTATION temp (A) = " || dump_info(temp))
		while \temp do { 
		    v := temp.cn_hd_field
		    add_id::add_id(v, x)
		    temp := temp.cn_tl_field
		    write(sym2file,"BLOCKDENOTATION temp (B) = " || dump_info(temp))
		}
		# Process declaration signatures, declaration denotations, 
		# and the block denotation.
		temp := x.bld_declaration_list.lh_first
		while \temp do { 
		    v := temp.cn_hd_field
		    build_symtab(v.decl_signature)
		    build_symtab(v.decl_denotation)
		    temp := temp.cn_tl_field
		}
		write(sym2file,"BLOCKDENOTATION bld_den_seq = " || dump_info(x.bld_den_seq))
		x.dump(sym2file)
		build_symtab(x.bld_den_seq)
		
		# Restore surrounding scope.
		temp := x.bld_declaration_list.lh_first
		while \temp do 
		    {
			v := temp.cn_hd_field
			restore(v)
			temp := temp.cn_tl_field
		    }
	    }
	USELIST: 
	    {
		x.usl_previous_list := usl_ptr
		# Process list of types with old use list. 
		build_symtab(x.usl_type_list)
		# Process body with new use list 
		usl_ptr := x
		build_symtab(x.usl_den_seq)
		# restore old usl_ptr value 
		usl_ptr := x.usl_previous_list
	    }
	
	APPLICATION: 
	    {
		# Process operator and args. 
		build_symtab(x.ap_operator)
		build_symtab(x.ap_args)
	    }
	ENUMERATION:
	    {
		temp := x.enum_id_list.lh_first
		while \temp do {
		    v := temp.cn_hd_field
		    x . id_last_definition = x
		    temp := temp.cn_tl_field
		}
	    }
	EXTENSION:
	    {
		# Process denotation. 
		build_symtab(x.ext_denotation)
	    }
	UNIONCONSTRUCTION: 
	    {
		# Add local type name to symtab. 
		add_id::add_id(x, x)
		if (x . kind = PRODCONSTRUCTION) then 
		    {
			# Add field names to symtab. 
			temp := x.prod_components.lh_first
			while \temp do {
			    v := temp.cn_hd_field
			    add_id::add_id(v,x)
			    temp := temp.cn_tl_field
			}
		    }
		
		# Process the component signatures
		temp := x.prod_components.lh_first
		while \temp do
		    {
			v := temp.cn_hd_field
			build_symtab(v.par_signature)
			temp := temp.cn_tl_field
		    }
		# Restore surrounding scope. 
		restore(x)
		if (x . kind = PRODCONSTRUCTION) then
		    {
			temp := x.prod_components.lh_first
			while \temp do
			    {
				v := temp.cn_hd_field
				restore(v)
				temp := temp.cn_tl_field
			    }
		    }
	    }
	PRODCONSTRUCTION: 
	    { 
		# Add local type name to symtab. 
		add_id::add_id(x, x)
		if (x . kind = PRODCONSTRUCTION) then 
		    {
			# Add field names to symtab. 
			temp := x.prod_components.lh_first
			while \temp do {
			    v := temp.cn_hd_field
			    add_id::add_id(v,x)
			    temp := temp.cn_tl_field
			}
		    }
		
		# Process the component signatures
		temp := x.prod_components.lh_first
		while \temp do
		    {
			v := temp.cn_hd_field
			build_symtab(v.par_signature)
			temp := temp.cn_tl_field
		    }
		# Restore surrounding scope. 
		restore(x)
		if (x . kind = PRODCONSTRUCTION) then
		    {
			temp := x.prod_components.lh_first
			while \temp do
			    {
				v := temp.cn_hd_field
				restore(v)
				temp := temp.cn_tl_field
			    }
		    }
	    }
	RECORDCONSTRUCTION: 
	    {
		# Process record component denotations.
		temp := x.rec_component_list.lh_first
		while \temp do {
		    v := temp.cn_hd_field
		    v . re_id . id_last_definition := v . re_id
		    build_symtab(v.re_denotation)
		    temp := temp.cn_tl_field
		}
	    }
	WITHLIST: 
	    {
		# Process declaration denotations.
		temp := x.wl_component_list.lh_first
		while \temp do {
		    v := temp.cn_hd_field
		    v . decl_id . id_last_definition := nil
		    build_symtab(v.decl_signature)
		    build_symtab(v.decl_denotation)
		    temp := temp.cn_tl_field
		}
	    }
	MODPRIMARY: 
	    {
		# Process primary and modifier. 
		build_symtab(x.mp_primary)
		# add local id to symtab 
		add_id::add_id(x,x)
		build_symtab(x.mp_type_modifier)
		# restore surrounding scope 
		restore(x)
	    }
	
	EXPORTLIST: 
	    {
		# Process the export element list. 
		build_symtab(x.cn_hd_field.el_export_element_list)
	    }
	HIDELIST: 
	    {
		# Process the export element list. 
		build_symtab(x.el_export_element_list)
	    }
	
	EXPORTELEMENT: 
	    {
		x . ee_id . id_last_definition := x . ee_id
		build_symtab(x . ee_signature)
		build_symtab(x . ee_export_list)
	    }
	
	ALLCONSTANTS: 
	    {
		# Nothing to do. 
	    }
	WORDELSE: {}
	# Nothing to do. 
	WORDCAND: 
	    {
		# Nothing to do. 
	    }
	WORDCOR: 
	    {
		# Nothing to do. 
	    }
	GUARDEDLIST: 
	    {
		# Process guarded list. 
		build_symtab(x.gl_list)
	    }
	LOOPDENOTATION: 
	    {
		# Process guarded list. 
		build_symtab(x.gl_list)
	    }
	GUARDEDELEMENT: 
	    {
		# Process guard and element. 
		build_symtab(x.ge_guard)
		build_symtab(x.ge_element)
	    }
	
	OPRID: 
	    
	    {
		# Just a use, not a definition. 
		# Process selection type and signature 
		build_symtab(x.sel_type)
		build_symtab(x.signature)
		# Fill in last definition field. 
		process_id(x)
	    }
	LETTERID:
	    {
		# Process selection type and signature 
		build_symtab(x.sel_type)
		build_symtab(x.signature)
		# Fill in last definition field. 
		process_id(x)
	    }
	
	
	QSTR:
	    {
		# process selection type 
		build_symtab(x . sel_type)
		# fill in use list field 
		x.str_use_list := usl_ptr
	    }
	UQSTR: 
	    {
		# process selection type 
		build_symtab(x . sel_type)
		# fill in use list field 
		x.str_use_list := usl_ptr
	    }
	
	
	FUNCCONSTR: 
	    {
		# Add the parameter identifiers to symtab. 
		temp := x.signature.fsig_param_list.lh.first
		while \temp do 
		    { 
			v := temp.cn_hd_field
			add_id::add_id(v, x)
			temp := temp.cn_tl_field
		    }
		# Process the parameter signatures, the function result 
		# signature, and the function body. 
		temp := x.signature.fsig_param_list.lh_field
		while \temp do 
		    {
			v := temp.cn_hd_field
			build_symtab(v.par_signature)
			temp := temp.cn_tl_field
		    }
		build_symtab(x.signature.fsig_result_sig)
		build_symtab(x.fc_body)
		
		# Restore surrounding scope.
		temp :=  x.signature.fsig_param_list.lh_first
		while \temp do 
		    {
			v := temp.cn_hd_field
			restore(v)
			temp := temp.cn_tl_field
		    }
	    }
	REXTERNDEF: 
	    {
	    }
	EXTERNDEF: 
	    {
	    }
    }
    return TRUE
end
