MCPcopy Index your code
hub / github.com/endbasic/endbasic / compile_user_callable

Function compile_user_callable

core/src/compiler/top.rs:1117–1190  ·  view source on GitHub ↗

Compiles a single user-defined callable.

(
    ctx: &mut Context,
    symtable: &mut GlobalSymtable,
    callable: CallableSpan,
)

Source from the content-addressed store, hash-verified

1115
1116/// Compiles a single user-defined callable.
1117fn compile_user_callable(
1118 ctx: &mut Context,
1119 symtable: &mut GlobalSymtable,
1120 callable: CallableSpan,
1121) -> Result<()> {
1122 if ctx.current_callable.is_some() {
1123 return Err(Error::CannotNestUserCallables(callable.name_pos));
1124 }
1125
1126 let skip_pc = ctx.codegen.emit(bytecode::make_nop(), callable.name_pos);
1127
1128 let start_pc = ctx.codegen.next_pc();
1129
1130 let key_pos = callable.name_pos;
1131 let key = SymbolKey::from(callable.name.name);
1132 ctx.current_callable = Some(if callable.name.ref_type.is_some() {
1133 CallableKind::Function
1134 } else {
1135 CallableKind::Sub
1136 });
1137 debug_assert!(ctx.callable_exit_jumps.is_empty());
1138
1139 let mut symtable = symtable.enter_scope();
1140
1141 // The call protocol expects the return value to be in the first local variable
1142 // so allocate it early, and then all arguments follow in order from left to right.
1143 if let Some(vtype) = callable.name.ref_type {
1144 let ret_reg = symtable
1145 .put_local(key.clone(), SymbolPrototype::Scalar(vtype))
1146 .map_err(|e| Error::from_syms(e, key_pos))?;
1147
1148 // Set the default value of the function result. We could instead try to do this
1149 // at runtime by clearning the return register... but the problem is that we need
1150 // to handle non-primitive types like strings and the runtime doesn't know the type
1151 // of the result to properly allocate it.
1152 let value = match vtype {
1153 ExprType::Boolean | ExprType::Integer => 0,
1154 ExprType::Double => ctx.codegen.get_constant(ConstantDatum::Double(0.0), key_pos)?,
1155 ExprType::Text => {
1156 ctx.codegen.get_constant(ConstantDatum::Text(String::new()), key_pos)?
1157 }
1158 };
1159 ctx.codegen.emit(bytecode::make_load_integer(ret_reg, value), key_pos);
1160 }
1161 for param in callable.params {
1162 let key = SymbolKey::from(param.name);
1163 symtable
1164 .put_local(
1165 key.clone(),
1166 SymbolPrototype::Scalar(param.ref_type.unwrap_or(ExprType::Integer)),
1167 )
1168 .map_err(|e| Error::from_syms(e, key_pos))?;
1169 }
1170
1171 for stmt in callable.body {
1172 compile_stmt(ctx, &mut symtable, stmt)?;
1173 }
1174

Callers 1

compile_stmtFunction · 0.85

Calls 8

compile_stmtFunction · 0.85
emitMethod · 0.80
next_pcMethod · 0.80
enter_scopeMethod · 0.80
put_localMethod · 0.80
get_constantMethod · 0.80
patchMethod · 0.80
define_user_callableMethod · 0.80

Tested by

no test coverage detected