microcad_lang/eval/call/
mod.rs1#[macro_use]
7mod argument;
8mod argument_value;
9mod argument_value_list;
10mod call_method;
11mod call_trait;
12
13pub use argument_value::ArgumentValue;
14pub use argument_value_list::ArgumentValueList;
15pub use call_method::*;
16pub use call_trait::*;
17use microcad_lang_base::{Identifier, SrcReferrer};
18
19use crate::{eval::*, lower::ir, symbol::SymbolDef, value::*};
20
21impl Eval<ArgumentValueList> for ir::ArgumentList {
22 fn eval(&self, context: &mut EvalContext) -> EvalResult<ArgumentValueList> {
24 self.iter()
25 .map(|arg| {
26 (
27 arg.id.clone().unwrap_or(Identifier::none()),
28 arg.eval(context),
29 )
30 })
31 .map(|(id, arg)| match arg {
32 Ok(arg) => Ok((id.clone(), arg)),
33 Err(err) => Err(err),
34 })
35 .collect()
36 }
37}
38
39impl Eval for ir::Call {
40 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
41 let symbol = match context.lookup(&self.name, LookupTarget::Function) {
43 Ok(symbol) => symbol,
44 Err(err) => {
45 context.error(self, err)?;
46 return Ok(Value::None);
47 }
48 };
49
50 let args: ArgumentValueList = self.argument_list.eval(context)?;
52
53 log::debug!(
54 "{call} {name:?}({args:?})",
55 name = self.name,
56 call = microcad_lang_base::mark!(CALL),
57 );
58
59 match context.scope(
60 StackFrame::Call {
61 symbol: symbol.clone(),
62 args: args.clone(),
63 src_ref: self.src_ref(),
64 },
65 |context| {
66 symbol.with_def(|def| match def {
67 SymbolDef::Builtin(f) => f.call(&args, context),
68 SymbolDef::Workbench(w) => {
69 if matches!(*w.kind, ir::WorkbenchKind::Operation) {
70 context.error(self, EvalError::CannotCallOperationWithoutWorkpiece)?;
71 Ok(Value::None)
72 } else {
73 Ok(Value::Model(w.call(
74 self.src_ref(),
75 symbol.clone(),
76 &args,
77 context,
78 )?))
79 }
80 }
81 SymbolDef::Function(f) => f.call(&args, context),
82 _ => {
83 context.error(self, EvalError::SymbolCannotBeCalled(symbol.full_name()))?;
84 Ok(Value::None)
85 }
86 })
87 },
88 ) {
89 Ok(value) => Ok(value),
90 Err(err) => {
91 context.error(self, err)?;
92 Ok(Value::None)
93 }
94 }
95 }
96}