Compiles the arguments of a callable invocation. Returns the first register containing the compiled arguments and the source positions for all allocated registers. The register layout depends on the callable's syntax: Singular arguments and variable repeated arguments use `VarArgTag` tag registers followed by optional value registers. See the `VarArgTag` documentation for details. Repeated ar
(
span: CallSpan,
md: Rc<CallableMetadata>,
symtable: &mut TempSymtable<'_, '_>,
codegen: &mut Codegen,
)
| 203 | /// another lookup from the symtable. Or maybe we could make `Metadata` objects static by |
| 204 | /// eliminating the `MetadataBuilder` and pass a static reference here. |
| 205 | pub(super) fn compile_args( |
| 206 | span: CallSpan, |
| 207 | md: Rc<CallableMetadata>, |
| 208 | symtable: &mut TempSymtable<'_, '_>, |
| 209 | codegen: &mut Codegen, |
| 210 | ) -> Result<(Register, Vec<LineCol>)> { |
| 211 | let key_pos = span.vref_pos; |
| 212 | |
| 213 | let Some(syntax) = md.find_syntax(span.args.len()) else { |
| 214 | return Err(Error::CallableSyntax(key_pos, md.as_ref().clone())); |
| 215 | }; |
| 216 | |
| 217 | let mut scope = symtable.temp_scope(); |
| 218 | |
| 219 | // Collects the source position for each register slot allocated below, in allocation order. |
| 220 | // This is used to populate the UPCALL instruction's arg_linecols metadata so that callables |
| 221 | // can query the source position of any argument via `Scope::get_pos`. |
| 222 | let mut arg_linecols: Vec<LineCol> = Vec::new(); |
| 223 | |
| 224 | let input_nargs = span.args.len(); |
| 225 | let mut arg_iter = span.args.into_iter().peekable(); |
| 226 | |
| 227 | for (i, syn) in syntax.singular.iter().enumerate() { |
| 228 | let end_ok = i + 1 == syntax.singular.len() |
| 229 | && input_nargs == syntax.singular.len() |
| 230 | && syntax.repeated.as_ref().is_some_and(|syn| !syn.require_one); |
| 231 | |
| 232 | match syn { |
| 233 | SingularArgSyntax::RequiredValue(details, exp_sep) => { |
| 234 | let ArgSpan { expr, sep, sep_pos } = |
| 235 | arg_iter.next().expect("Args and their syntax must advance in unison"); |
| 236 | let arg_pos = expr.as_ref().map(|e| e.start_pos()).unwrap_or(sep_pos); |
| 237 | |
| 238 | match expr { |
| 239 | None => return Err(Error::CallableSyntax(key_pos, md.as_ref().clone())), |
| 240 | Some(expr) => { |
| 241 | let temp_value = scope.alloc().map_err(|e| Error::from_syms(e, arg_pos))?; |
| 242 | arg_linecols.push(arg_pos); |
| 243 | compile_expr_as_type(codegen, symtable, temp_value, expr, details.vtype)?; |
| 244 | validate_syn_argsep( |
| 245 | &md, |
| 246 | exp_sep, |
| 247 | end_ok, |
| 248 | arg_iter.peek().is_none(), |
| 249 | sep, |
| 250 | sep_pos, |
| 251 | )?; |
| 252 | } |
| 253 | } |
| 254 | } |
| 255 | |
| 256 | SingularArgSyntax::RequiredRef(details, exp_sep) => { |
| 257 | let ArgSpan { expr, sep, sep_pos } = |
| 258 | arg_iter.next().expect("Args and their syntax must advance in unison"); |
| 259 | let arg_pos = expr.as_ref().map(|e| e.start_pos()).unwrap_or(sep_pos); |
| 260 | |
| 261 | match expr { |
| 262 | None => return Err(Error::CallableSyntax(key_pos, md.as_ref().clone())), |