microcad_lang/eval/call/
mod.rs1#[macro_use]
7mod argument;
8mod call_method;
9mod call_trait;
10
11pub use call_method::*;
12pub use call_trait::*;
13use microcad_lang_base::SrcReferrer;
14
15use crate::{eval::*, symbol::SymbolDef, syntax::*, value::*};
16
17use thiserror::Error;
18
19impl Eval<ArgumentValueList> for ArgumentList {
20 fn eval(&self, context: &mut EvalContext) -> EvalResult<ArgumentValueList> {
22 self.iter()
23 .map(|arg| {
24 (
25 arg.id.clone().unwrap_or(Identifier::none()),
26 arg.eval(context),
27 )
28 })
29 .map(|(id, arg)| match arg {
30 Ok(arg) => Ok((id.clone(), arg)),
31 Err(err) => Err(err),
32 })
33 .collect()
34 }
35}
36
37impl Eval for Call {
38 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
39 let symbol = match context.lookup(&self.name, LookupTarget::Function) {
41 Ok(symbol) => symbol,
42 Err(err) => {
43 context.error(self, err)?;
44 return Ok(Value::None);
45 }
46 };
47
48 let args: ArgumentValueList = self.argument_list.eval(context)?;
50
51 log::debug!(
52 "{call} {name:?}({args:?})",
53 name = self.name,
54 call = microcad_lang_base::mark!(CALL),
55 );
56
57 match context.scope(
58 StackFrame::Call {
59 symbol: symbol.clone(),
60 args: args.clone(),
61 src_ref: self.src_ref(),
62 },
63 |context| {
64 symbol.with_def(|def| match def {
65 SymbolDef::Builtin(f) => f.call(&args, context),
66 SymbolDef::Workbench(w) => {
67 if matches!(*w.kind, WorkbenchKind::Operation) {
68 context.error(self, EvalError::CannotCallOperationWithoutWorkpiece)?;
69 Ok(Value::None)
70 } else {
71 Ok(Value::Model(w.call(
72 self.src_ref(),
73 symbol.clone(),
74 &args,
75 context,
76 )?))
77 }
78 }
79 SymbolDef::Function(f) => f.call(&args, context),
80 _ => {
81 context.error(self, EvalError::SymbolCannotBeCalled(symbol.full_name()))?;
82 Ok(Value::None)
83 }
84 })
85 },
86 ) {
87 Ok(value) => Ok(value),
88 Err(err) => {
89 context.error(self, err)?;
90 Ok(Value::None)
91 }
92 }
93 }
94}
95
96#[derive(Error, Debug)]
98pub enum MatchError {
99 #[error("Duplicated argument: {0}")]
101 DuplicatedArgument(Identifier),
102 #[error("Parameter `{0}` is not defined.")]
104 ParameterNotDefined(Identifier),
105 #[error("Type mismatch for parameter `{0}`: expected `{1}`, got {2}")]
107 PositionalArgumentTypeMismatch(Identifier, Type, Type),
108 #[error("Missing parameter: {0}")]
110 MissingParameter(Identifier),
111}