| 106 | } |
| 107 | |
| 108 | fn exec(&self, mut scope: Scope<'_>) -> CallResult<()> { |
| 109 | debug_assert_ne!(0, scope.nargs()); |
| 110 | |
| 111 | fn assign_datum(scope: &mut Scope<'_>, reg: u8, datum: ConstantDatum) -> CallResult<()> { |
| 112 | let target_type = scope.get_ref(reg).vtype; |
| 113 | match (target_type, datum) { |
| 114 | (ExprType::Boolean, ConstantDatum::Boolean(b)) => { |
| 115 | scope.get_mut_ref(reg).set_boolean(b); |
| 116 | Ok(()) |
| 117 | } |
| 118 | (ExprType::Double, ConstantDatum::Double(d)) => { |
| 119 | scope.get_mut_ref(reg).set_double(d); |
| 120 | Ok(()) |
| 121 | } |
| 122 | (ExprType::Double, ConstantDatum::Integer(i)) => { |
| 123 | scope.get_mut_ref(reg).set_double(i as f64); |
| 124 | Ok(()) |
| 125 | } |
| 126 | (ExprType::Integer, ConstantDatum::Double(d)) => { |
| 127 | let i = double_to_integer(d) |
| 128 | .map_err(|e| CallError::Syntax(scope.get_pos(reg), e.to_string()))?; |
| 129 | scope.get_mut_ref(reg).set_integer(i); |
| 130 | Ok(()) |
| 131 | } |
| 132 | (ExprType::Integer, ConstantDatum::Integer(i)) => { |
| 133 | scope.get_mut_ref(reg).set_integer(i); |
| 134 | Ok(()) |
| 135 | } |
| 136 | (ExprType::Text, ConstantDatum::Text(s)) => { |
| 137 | scope.get_mut_ref(reg).set_string(s)?; |
| 138 | Ok(()) |
| 139 | } |
| 140 | (target_type, source_value) => Err(CallError::Syntax( |
| 141 | scope.get_pos(reg), |
| 142 | format!( |
| 143 | "Cannot assign value of type {} to variable of type {}", |
| 144 | value_type_name(&source_value), |
| 145 | expr_type_name(target_type), |
| 146 | ), |
| 147 | )), |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | let mut index = self.index.borrow_mut(); |
| 152 | let mut reg = 0; |
| 153 | loop { |
| 154 | let sep = if let VarArgTag::Pointer(sep) = scope.get_type(reg) { |
| 155 | sep |
| 156 | } else { |
| 157 | unreachable!(); |
| 158 | }; |
| 159 | reg += 1; |
| 160 | |
| 161 | let vtype = scope.get_ref(reg).vtype; |
| 162 | let datum = match scope.data().get(*index) { |
| 163 | None => { |
| 164 | return Err(CallError::Syntax(scope.get_pos(reg), "Out of data".to_owned())); |
| 165 | } |