euphoria

changeset 5547:0733e000f389 4.0

* delayed resolution of default parameter values, including updated unit tests
* fixes ticket 563
author Matt Lewis
date Thu Apr 26 15:19:06 2012 -0400 (13 months ago)
parents 37e21790b20c
children d2d529ba243f
files source/fwdref.e source/parser.e tests/defparam1.e tests/defparam2.e tests/t_defparms.e
line diff
     1.1 --- a/source/fwdref.e	Wed Apr 25 07:46:42 2012 -0400
     1.2 +++ b/source/fwdref.e	Thu Apr 26 15:19:06 2012 -0400
     1.3 @@ -224,14 +224,26 @@
     1.4  	-- pc+3 Args... [/ Func target]
     1.5  	
     1.6  	sequence fr = forward_references[ref]
     1.7 +	symtab_index sub = tok[T_SYM]
     1.8 +
     1.9 +	if sequence( fr[FR_DATA] ) then
    1.10 +		sequence defarg = fr[FR_DATA][1]
    1.11 +		symtab_index paramsym = defarg[2]
    1.12 +		token old = { RECORDED, defarg[3] }
    1.13 +		integer tx = find( old, SymTab[paramsym][S_CODE] )
    1.14 +		SymTab[paramsym][S_CODE][tx] = tok
    1.15 +		resolved_reference( ref )
    1.16 +		return
    1.17 +	end if
    1.18 +	
    1.19  	integer code_sub = fr[FR_SUBPROG]
    1.20 -	symtab_index sub = tok[T_SYM]
    1.21 +	
    1.22  	integer args = SymTab[sub][S_NUM_ARGS]
    1.23  	integer is_func = (SymTab[sub][S_TOKEN] = FUNC) or (SymTab[sub][S_TOKEN] = TYPE)
    1.24  	
    1.25  	integer real_file = current_file_no
    1.26  	current_file_no = fr[FR_FILE]
    1.27 -	
    1.28 +
    1.29  	set_code( ref )
    1.30  	sequence code = Code
    1.31  	integer temp_sub = CurrentSub
    1.32 @@ -240,7 +252,7 @@
    1.33  	integer next_pc = pc
    1.34  	integer supplied_args = code[pc+2]
    1.35  	sequence name = fr[FR_NAME]
    1.36 -	
    1.37 +
    1.38  	if Code[pc] != FUNC_FORWARD and Code[pc] != PROC_FORWARD then
    1.39  		prep_forward_error( ref )
    1.40  		CompileErr( "The forward call to [4] wasn't where we thought it would be: [1]:[2]:[3]",
    1.41 @@ -417,6 +429,20 @@
    1.42  		end while
    1.43  		resolved_reference( ref )
    1.44  	end if
    1.45 +
    1.46 +	if sequence( fr[FR_DATA] ) then
    1.47 +		for i = 1 to length( fr[FR_DATA] ) do
    1.48 +			object d = fr[FR_DATA][i]
    1.49 +			if sequence( d ) and d[1] = PAM_RECORD then
    1.50 +				-- resolving default parameter tokens
    1.51 +				symtab_index param = d[2]
    1.52 +				token old = {RECORDED, d[3]}
    1.53 +				token new = {VARIABLE, sym}
    1.54 +				SymTab[param][S_CODE] = find_replace( old, SymTab[param][S_CODE], new )
    1.55 +			end if
    1.56 +		end for
    1.57 +		resolved_reference( ref )
    1.58 +	end if
    1.59  	reset_code()
    1.60  end procedure
    1.61  
    1.62 @@ -424,8 +450,15 @@
    1.63  -- forward reference for a variable
    1.64  	sequence fr = forward_references[ref]
    1.65  	set_code( ref )
    1.66 -	Code[fr[FR_PC]+1] = tok[T_SYM]
    1.67 -	resolved_reference( ref )
    1.68 +	if sequence( fr[FR_DATA] ) then
    1.69 +		-- init check in default param code
    1.70 +		resolved_reference( ref )
    1.71 +	elsif fr[FR_PC] > 0 then
    1.72 +		Code[fr[FR_PC]+1] = tok[T_SYM]
    1.73 +		resolved_reference( ref )
    1.74 +	else
    1.75 +		forward_error( tok, ref )
    1.76 +	end if
    1.77  	reset_code()
    1.78  end procedure
    1.79  
    1.80 @@ -696,6 +729,7 @@
    1.81  	integer 
    1.82  		ref, 
    1.83  		len = length( inactive_references )
    1.84 +
    1.85  	
    1.86  	if len then
    1.87  		ref = inactive_references[len]
    1.88 @@ -742,32 +776,54 @@
    1.89  	-- If we're recording tokens (for a default parameter), this ref will never 
    1.90  	-- get resolved.  So ignore it for now, and when someone actually calls
    1.91  	-- the routine, it will be resolved normally then.
    1.92 -	if  Parser_mode != PAM_RECORD then
    1.93 -		if CurrentSub = TopLevelSub then
    1.94 -			if length( toplevel_references ) < current_file_no then
    1.95 -				toplevel_references &= repeat( {}, current_file_no - length( toplevel_references ) )
    1.96 -			end if
    1.97 -			toplevel_references[current_file_no] &= ref
    1.98 -		else
    1.99 -			if length( active_references ) < current_file_no then
   1.100 -				active_references &= repeat( {}, current_file_no - length( active_references ) )
   1.101 -				active_subprogs   &= repeat( {}, current_file_no - length( active_subprogs ) )
   1.102 -			end if
   1.103 -			integer sp = find( CurrentSub, active_subprogs[current_file_no] )
   1.104 -			if not sp then
   1.105 -				active_subprogs[current_file_no] &= CurrentSub
   1.106 -				sp = length( active_subprogs[current_file_no] )
   1.107 -				
   1.108 -				active_references[current_file_no] = append( active_references[current_file_no], {} )
   1.109 -			end if
   1.110 -			active_references[current_file_no][sp] &= ref
   1.111 +	
   1.112 +	if CurrentSub = TopLevelSub then
   1.113 +		if length( toplevel_references ) < current_file_no then
   1.114 +			toplevel_references &= repeat( {}, current_file_no - length( toplevel_references ) )
   1.115  		end if
   1.116 -		fwdref_count += 1
   1.117 +		toplevel_references[current_file_no] &= ref
   1.118 +	else
   1.119 +		add_active_reference( ref )
   1.120 +
   1.121 +		if Parser_mode = PAM_RECORD then
   1.122 +			symtab_pointer default_sym = CurrentSub
   1.123 +			symtab_pointer param = 0
   1.124 +			while default_sym with entry do
   1.125 +				if sym_scope( default_sym ) = SC_PRIVATE then
   1.126 +					param = default_sym
   1.127 +				end if
   1.128 +			entry
   1.129 +				default_sym = sym_next( default_sym )
   1.130 +			end while
   1.131 +			set_data( ref, {{ PAM_RECORD, param, length( Recorded_sym ) }} )
   1.132 +		end if
   1.133  	end if
   1.134 +	fwdref_count += 1
   1.135  	
   1.136  	return ref
   1.137  end function
   1.138  
   1.139 +procedure add_active_reference( integer ref, integer file_no = current_file_no )
   1.140 +	if length( active_references ) < file_no then
   1.141 +		active_references &= repeat( {}, file_no - length( active_references ) )
   1.142 +		active_subprogs   &= repeat( {}, file_no - length( active_subprogs ) )
   1.143 +	end if
   1.144 +	integer sp = find( CurrentSub, active_subprogs[file_no] )
   1.145 +	if not sp then
   1.146 +		active_subprogs[file_no] &= CurrentSub
   1.147 +		sp = length( active_subprogs[file_no] )
   1.148 +
   1.149 +		active_references[file_no] = append( active_references[file_no], {} )
   1.150 +	end if
   1.151 +	active_references[file_no][sp] &= ref
   1.152 +end procedure
   1.153 +
   1.154 +procedure remove_active_reference( integer ref, integer file_no = current_file_no )
   1.155 +	integer sp = find( CurrentSub, active_subprogs[file_no] )
   1.156 +	active_references[file_no][sp] = remove( active_references[file_no][sp],
   1.157 +											length( active_references[file_no][sp] ) )
   1.158 +end procedure
   1.159 +
   1.160  function resolve_file( sequence refs, integer report_errors, integer unincluded_ok )
   1.161  	
   1.162  	sequence errors = {}
   1.163 @@ -778,12 +834,13 @@
   1.164  		if include_matrix[fr[FR_FILE]][current_file_no] = NOT_INCLUDED and not unincluded_ok then
   1.165  			continue
   1.166  		end if
   1.167 +		
   1.168  		token tok = find_reference( fr )
   1.169  		if tok[T_ID] = IGNORED then
   1.170  			errors &= ref
   1.171  			continue
   1.172  		end if
   1.173 -		
   1.174 +
   1.175  		-- found a match...
   1.176  		integer code_sub = fr[FR_SUBPROG]
   1.177  		integer fr_type  = fr[FR_TYPE]
   1.178 @@ -817,6 +874,7 @@
   1.179  					errors &= ref
   1.180  					continue
   1.181  				end if
   1.182 +				
   1.183  				switch sym_tok do
   1.184  					case CONSTANT, ENUM, VARIABLE then
   1.185  						patch_forward_variable( tok, ref )
     2.1 --- a/source/parser.e	Wed Apr 25 07:46:42 2012 -0400
     2.2 +++ b/source/parser.e	Thu Apr 26 15:19:06 2012 -0400
     2.3 @@ -560,9 +560,9 @@
     2.4  	PS_ON_ARG
     2.5  
     2.6  sequence private_list = {}
     2.7 -integer lock_scanner = 0
     2.8 +export integer lock_scanner = 0
     2.9  integer on_arg = 0
    2.10 -sequence nested_calls = {}
    2.11 +export sequence nested_calls = {}
    2.12  
    2.13  procedure restore_parseargs_states()
    2.14  	sequence s
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tests/defparam1.e	Thu Apr 26 15:19:06 2012 -0400
     3.3 @@ -0,0 +1,9 @@
     3.4 +-- used by t_defparms.e
     3.5 +
     3.6 +include defparam2.e
     3.7 +
     3.8 +export function defparams( integer a = DEFPARAM1, integer b = DEFPARAM2 )
     3.9 +	return a + b
    3.10 +end function
    3.11 +
    3.12 +constant DEFPARAM1 = 1
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tests/defparam2.e	Thu Apr 26 15:19:06 2012 -0400
     4.3 @@ -0,0 +1,3 @@
     4.4 +-- used by t_defparms.e
     4.5 +
     4.6 +export constant DEFPARAM2  = 2
     5.1 --- a/tests/t_defparms.e	Wed Apr 25 07:46:42 2012 -0400
     5.2 +++ b/tests/t_defparms.e	Thu Apr 26 15:19:06 2012 -0400
     5.3 @@ -103,9 +103,12 @@
     5.4  	return a
     5.5  end function
     5.6  
     5.7 +include defparam1.e
     5.8  procedure test_563()
     5.9  	sequence s = "def"
    5.10  	test_equal( "resolve default parameter in its parsing context", defparams:s, t_563() )
    5.11 +	test_equal( "resolve default parameters as forward references from their parsing contexts",
    5.12 +				3, defparams() )
    5.13  end procedure
    5.14  test_563()
    5.15  

SCM Home | OpenEuphoria.org Home