Skip to content

Commit c84b12d

Browse files
authored
feat: impl lambda calling for the evaluator (#1167)
Signed-off-by: peefy <[email protected]>
1 parent f48aa81 commit c84b12d

26 files changed

+364
-171
lines changed

kclvm/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kclvm/evaluator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2021"
88
[dependencies]
99
indexmap = "1.0"
1010
anyhow = "1.0"
11+
generational-arena = "0.2.9"
1112
kclvm-ast = {path = "../ast"}
1213
kclvm-sema = {path = "../sema"}
1314
kclvm-runtime = {path = "../runtime"}

kclvm/evaluator/src/context.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::{
2+
collections::{HashMap, HashSet},
3+
sync::Arc,
4+
};
25

6+
use generational_arena::Index;
37
use indexmap::IndexMap;
48
use kclvm_error::Handler;
59
use kclvm_runtime::ValueRef;
610

7-
use crate::{error as kcl_error, function::FunctionValue, scope::Scope, Evaluator, GLOBAL_LEVEL};
11+
use crate::{error as kcl_error, func::FunctionProxy, scope::Scope, Evaluator, GLOBAL_LEVEL};
812

9-
#[derive(Debug)]
1013
pub struct EvaluatorContext {
11-
pub functions: Vec<FunctionValue>,
1214
pub imported: HashSet<String>,
1315
pub lambda_stack: Vec<usize>,
1416
pub schema_stack: Vec<()>,
@@ -42,7 +44,6 @@ pub struct EvaluatorContext {
4244
impl Default for EvaluatorContext {
4345
fn default() -> Self {
4446
Self {
45-
functions: Default::default(),
4647
imported: Default::default(),
4748
lambda_stack: vec![GLOBAL_LEVEL],
4849
schema_stack: Default::default(),
@@ -206,4 +207,10 @@ impl<'ctx> Evaluator<'ctx> {
206207
pub(crate) fn pop_pkgpath(&self) {
207208
self.ctx.borrow_mut().pkgpath_stack.pop();
208209
}
210+
211+
/// Append a function into the scope
212+
#[inline]
213+
pub fn add_function(&self, function: FunctionProxy) -> Index {
214+
self.functions.borrow_mut().insert(Arc::new(function))
215+
}
209216
}

kclvm/evaluator/src/func.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use std::fmt::Debug;
2+
use std::sync::Arc;
3+
4+
use generational_arena::Index;
5+
use kclvm_ast::ast;
6+
use kclvm_runtime::ValueRef;
7+
8+
use crate::error as kcl_error;
9+
use crate::Evaluator;
10+
11+
pub type FunctionHandler =
12+
Arc<dyn Fn(&Evaluator, &ast::LambdaExpr, &ValueRef, &ValueRef) -> ValueRef>;
13+
14+
/// Proxy functions represent the saved functions of the runtime itself,
15+
/// rather than executing KCL defined functions or plugin functions.
16+
#[derive(Clone)]
17+
pub struct FunctionProxy {
18+
lambda_expr: ast::LambdaExpr,
19+
inner: FunctionHandler,
20+
}
21+
22+
impl Debug for FunctionProxy {
23+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24+
let ptr_value = Arc::as_ptr(&self.inner);
25+
f.debug_struct("FunctionProxy")
26+
.field("inner", &format!("{ptr_value:p}"))
27+
.finish()
28+
}
29+
}
30+
31+
impl FunctionProxy {
32+
#[inline]
33+
pub fn new(lambda_expr: ast::LambdaExpr, proxy: FunctionHandler) -> Self {
34+
Self {
35+
lambda_expr,
36+
inner: proxy,
37+
}
38+
}
39+
}
40+
41+
impl<'ctx> Evaluator<'ctx> {
42+
#[inline]
43+
pub(crate) fn invoke_proxy_function(
44+
&self,
45+
proxy_index: Index,
46+
args: &ValueRef,
47+
kwargs: &ValueRef,
48+
) -> ValueRef {
49+
let proxy = {
50+
let functions = self.functions.borrow();
51+
functions
52+
.get(proxy_index)
53+
.expect(kcl_error::INTERNAL_ERROR_MSG)
54+
.clone()
55+
};
56+
(proxy.inner)(self, &proxy.lambda_expr, args, kwargs)
57+
}
58+
}

kclvm/evaluator/src/function.rs

Lines changed: 0 additions & 15 deletions
This file was deleted.

kclvm/evaluator/src/lib.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod tests;
66
pub(crate) mod calculation;
77
pub(crate) mod context;
88
pub(crate) mod error;
9-
pub(crate) mod function;
9+
pub(crate) mod func;
1010
pub(crate) mod module;
1111
pub(crate) mod node;
1212
pub(crate) mod scope;
@@ -15,9 +15,10 @@ pub(crate) mod value;
1515
extern crate kclvm_error;
1616

1717
use context::EvaluatorContext;
18-
use kclvm_ast::walker::TypedResultWalker;
19-
use std::cell::RefCell;
18+
use func::FunctionProxy;
19+
use generational_arena::Arena;
2020
use std::str;
21+
use std::{cell::RefCell, sync::Arc};
2122

2223
use crate::error as kcl_error;
2324
use anyhow::Result;
@@ -39,28 +40,35 @@ pub struct Evaluator<'ctx> {
3940
pub program: &'ctx ast::Program,
4041
pub ctx: RefCell<EvaluatorContext>,
4142
pub runtime_ctx: RefCell<Context>,
43+
pub functions: RefCell<Arena<Arc<FunctionProxy>>>,
4244
}
4345

4446
impl<'ctx> Evaluator<'ctx> {
45-
/// New aa Evaluator using the LLVM Context and AST Program
47+
/// New aa Evaluator using the AST program
48+
#[inline]
4649
pub fn new(program: &'ctx ast::Program) -> Evaluator<'ctx> {
50+
Self::new_with_runtime_ctx(program, Context::new())
51+
}
52+
53+
/// New aa Evaluator using the AST program and runtime context
54+
#[inline]
55+
pub fn new_with_runtime_ctx(
56+
program: &'ctx ast::Program,
57+
runtime_ctx: Context,
58+
) -> Evaluator<'ctx> {
4759
Evaluator {
4860
ctx: RefCell::new(EvaluatorContext::default()),
49-
runtime_ctx: RefCell::new(Context::new()),
61+
runtime_ctx: RefCell::new(runtime_ctx),
5062
program,
63+
functions: RefCell::new(Arena::new()),
5164
}
5265
}
5366

54-
/// Generate LLVM IR of ast module.
67+
/// Evaluate the program
5568
pub fn run(self: &Evaluator<'ctx>) -> Result<(String, String)> {
56-
self.init_scope(kclvm_ast::MAIN_PKG);
57-
for module in self
58-
.program
59-
.pkgs
60-
.get(kclvm_ast::MAIN_PKG)
61-
.unwrap_or(&vec![])
62-
{
63-
self.walk_module(module)?;
69+
if let Some(modules) = self.program.pkgs.get(kclvm_ast::MAIN_PKG) {
70+
self.init_scope(kclvm_ast::MAIN_PKG);
71+
self.compile_ast_modules(modules)
6472
}
6573
Ok(self.plan_globals_to_string())
6674
}

0 commit comments

Comments
 (0)