euphoria
changeset 5547:0733e000f389 4.0
* delayed resolution of default parameter values, including updated unit tests
* fixes ticket 563
* 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
