microcad_lang/eval/mod.rs
1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Evaluation of parsed content.
5//!
6//! To be able to evaluate (run) a source file, it must be loaded, parsed and resolved.
7//! To do so a [`Context`] can be created with [`Context::new()`] based on an already resolved symbol or
8//! by using [`Context::from_source()`] or `ContextBuilder::from_source_captured()` which both automatically
9//! load and resolve the source file and build a context around it which then can be evaluated with [`Context::eval()`]:
10//!
11//! ```ignore
12//! use microcad_lang::eval::Context;
13//! use microcad_lang::diag::Diag;
14//! use std::io::stdout;
15//!
16//! // create a context for evaluation of the source file
17//! let mut context = Context::from_source(
18//! "my.µcad", // root file name
19//! builtin_module(), // `__builtin` library
20//! &["./lib".into()] // list of library paths
21//! ).expect("successful load, parse and resolve");
22//!
23//! // evaluate the source file in it's context
24//! let node = context.eval().expect("successful evaluation");
25//!
26//! // print any error
27//! println!("{}", context.diagnosis());
28//! ```
29
30mod argument_match;
31mod attribute;
32mod body;
33mod call;
34mod context;
35mod eval_error;
36mod expression;
37
38mod format_string;
39mod function;
40mod init;
41mod literal;
42mod module_definition;
43mod output;
44mod parameter;
45mod source_file;
46mod statements;
47mod symbols;
48mod tuple;
49mod workbench;
50
51pub use argument_match::*;
52pub use attribute::*;
53pub use call::*;
54pub use context::*;
55pub use eval_error::*;
56pub use output::*;
57pub use statements::*;
58pub use symbols::*;
59
60use crate::{diag::*, resolve::*, src_ref::*, syntax::*, ty::*, value::*};
61
62/// Evaluation trait.
63///
64/// The return type `T` defines to which output type the type is evaluated.
65/// Usually, these output types are used in specific context:
66///
67/// | Return type `T` | Context / Scope | Return value on error | Description |
68/// | ------------------- | --------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------- |
69/// | `()` | [`Assignment`]. | `()` | An assignment returns nothing but alters the symbol table. |
70/// | | | |
71/// | `Value` | Function calls, module statements, | `Value::None` | These trait implementations are
72/// | | parameter lists, argument lists. | | mostly used when evaluating functions.
73/// | | | |
74/// | `Option<Model>` | Workbenches, object bodies, source files, if. | `None` | Something is evaluated into a single model. |
75/// | | | |
76/// | `Models` | Statement, statement list, body, multiplicities. | `Models::default()` | A collection of models . |
77pub trait Eval<T = Value> {
78 /// Evaluate a syntax element into a type `T`.
79 fn eval(&self, context: &mut Context) -> EvalResult<T>;
80}
81
82impl MethodCall {
83 /// Evaluate method call.
84 ///
85 /// Examples:
86 /// ```microcad
87 /// assert([2.0, 2.0].all_equal(), "All elements in this list must be equal.");
88 /// ```
89 fn eval(&self, context: &mut Context, lhs: &Expression) -> EvalResult<Value> {
90 let value: Value = lhs.eval(context)?;
91 let args = self.argument_list.eval(context)?;
92 value.call_method(&self.id, &args, context)
93 }
94}
95
96/// Like `todo!()` but within a evaluation context
97///
98/// emits a diagnostic error instead of panicking.
99#[macro_export]
100macro_rules! eval_todo {
101 ($context: ident, $refer: ident, $($arg:tt)*) => {{
102 $context.error($refer, EvalError::Todo(format_args!($($arg)*).to_string()))?;
103 Ok(Value::None)
104 }}
105}
106
107pub use eval_todo;