artichoke_backend/extn/core/kernel/
trampoline.rs1use scolapasta_fixable::Fixable as _;
2
3use crate::convert::{check_string_type, check_to_int, to_i};
4use crate::extn::core::kernel;
5use crate::extn::core::kernel::require::RelativePath;
6use crate::extn::prelude::*;
7
8pub fn integer(interp: &mut Artichoke, mut val: Value, base: Option<Value>) -> Result<Value, Error> {
33 let base = if let Some(base) = base {
34 let converted_base = check_to_int(interp, base)?;
35 if converted_base.is_nil() {
36 None
37 } else {
38 Some(converted_base.try_convert_into::<i64>(interp)?)
39 }
40 } else {
41 None
42 };
43 if base.is_some() {
49 let tmp = check_string_type(interp, val)?;
50 if tmp.is_nil() {
51 return Err(ArgumentError::with_message("base specified for non string value").into());
53 }
54 val = tmp;
55 }
56
57 if let Ok(f) = val.try_convert_into::<f64>(interp) {
59 if f.is_infinite() {
65 return Err(
66 FloatDomainError::with_message(if f.is_sign_negative() { "-Infinity" } else { "Infinity" }).into(),
67 );
68 }
69 if f.is_nan() {
71 return Err(FloatDomainError::with_message("NaN").into());
72 }
73
74 if let Some(f) = f.to_fix() {
75 return Ok(interp.convert(f));
76 }
77 return Err(NotImplementedError::from("Float::to_fix does not support BigNum").into());
78 }
79
80 if let Ruby::Fixnum = val.ruby_type() {
82 return Ok(val);
83 }
84
85 if let Ok(subject) = unsafe { spinoso_string::String::unbox_from_value(&mut val, interp) } {
87 let i = scolapasta_int_parse::parse(subject.as_slice(), base)?;
94 return Ok(interp.convert(i));
95 }
96
97 if val.is_nil() {
99 return Err(TypeError::with_message("can't convert nil into Integer").into());
101 }
102
103 match check_to_int(interp, val) {
104 Ok(tmp) if tmp.ruby_type() == Ruby::Fixnum => return Ok(tmp),
105 _ => {}
106 }
107
108 to_i(interp, val)
112}
113
114pub fn load(interp: &mut Artichoke, path: Value) -> Result<Value, Error> {
115 let success = kernel::require::load(interp, path)?;
116 Ok(interp.convert(bool::from(success)))
117}
118
119pub fn print<T>(interp: &mut Artichoke, args: T) -> Result<Value, Error>
120where
121 T: IntoIterator<Item = Value>,
122{
123 for value in args {
124 let display = value.to_s(interp);
125 interp.print(&display)?;
126 }
127 Ok(Value::nil())
128}
129
130pub fn puts<T>(interp: &mut Artichoke, args: T) -> Result<Value, Error>
131where
132 T: IntoIterator<Item = Value>,
133{
134 fn puts_foreach(interp: &mut Artichoke, value: &Value) -> Result<(), Error> {
135 if let Ok(array) = value.try_convert_into_mut::<Vec<_>>(interp) {
139 for value in &array {
140 puts_foreach(interp, value)?;
141 }
142 } else {
143 let display = value.to_s(interp);
144 interp.puts(&display)?;
145 }
146 Ok(())
147 }
148
149 let mut args = args.into_iter();
150 if let Some(first) = args.next() {
151 puts_foreach(interp, &first)?;
152 for value in args {
153 puts_foreach(interp, &value)?;
154 }
155 } else {
156 interp.print(b"\n")?;
157 }
158 Ok(Value::nil())
159}
160
161pub fn p<T>(interp: &mut Artichoke, args: T) -> Result<Value, Error>
162where
163 T: IntoIterator<Item = Value>,
164{
165 let mut args = args.into_iter().peekable();
166 if let Some(first) = args.next() {
167 let display = first.inspect(interp);
168 interp.puts(&display)?;
169 if args.peek().is_none() {
170 return Ok(first);
171 }
172 let mut result = vec![first];
173 for value in args {
174 let display = value.inspect(interp);
175 interp.puts(&display)?;
176 result.push(value);
177 }
178 interp.try_convert_mut(result)
179 } else {
180 Ok(Value::nil())
181 }
182}
183
184pub fn require(interp: &mut Artichoke, path: Value) -> Result<Value, Error> {
185 let success = kernel::require::require(interp, path)?;
186 Ok(interp.convert(bool::from(success)))
187}
188
189pub fn require_relative(interp: &mut Artichoke, path: Value) -> Result<Value, Error> {
190 let relative_base = RelativePath::try_from_interp(interp)?;
191 let success = kernel::require::require_relative(interp, path, relative_base)?;
192 Ok(interp.convert(bool::from(success)))
193}