Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: impl lambda calling for the evaluator #1167

Merged
merged 1 commit into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions kclvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions kclvm/evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
indexmap = "1.0"
anyhow = "1.0"
generational-arena = "0.2.9"
kclvm-ast = {path = "../ast"}
kclvm-sema = {path = "../sema"}
kclvm-runtime = {path = "../runtime"}
Expand Down
17 changes: 12 additions & 5 deletions kclvm/evaluator/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::collections::{HashMap, HashSet};
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};

use generational_arena::Index;
use indexmap::IndexMap;
use kclvm_error::Handler;
use kclvm_runtime::ValueRef;

use crate::{error as kcl_error, function::FunctionValue, scope::Scope, Evaluator, GLOBAL_LEVEL};
use crate::{error as kcl_error, func::FunctionProxy, scope::Scope, Evaluator, GLOBAL_LEVEL};

#[derive(Debug)]
pub struct EvaluatorContext {
pub functions: Vec<FunctionValue>,
pub imported: HashSet<String>,
pub lambda_stack: Vec<usize>,
pub schema_stack: Vec<()>,
Expand Down Expand Up @@ -42,7 +44,6 @@ pub struct EvaluatorContext {
impl Default for EvaluatorContext {
fn default() -> Self {
Self {
functions: Default::default(),
imported: Default::default(),
lambda_stack: vec![GLOBAL_LEVEL],
schema_stack: Default::default(),
Expand Down Expand Up @@ -206,4 +207,10 @@ impl<'ctx> Evaluator<'ctx> {
pub(crate) fn pop_pkgpath(&self) {
self.ctx.borrow_mut().pkgpath_stack.pop();
}

/// Append a function into the scope
#[inline]
pub fn add_function(&self, function: FunctionProxy) -> Index {
self.functions.borrow_mut().insert(Arc::new(function))
}
}
58 changes: 58 additions & 0 deletions kclvm/evaluator/src/func.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use std::fmt::Debug;
use std::sync::Arc;

use generational_arena::Index;
use kclvm_ast::ast;
use kclvm_runtime::ValueRef;

use crate::error as kcl_error;
use crate::Evaluator;

pub type FunctionHandler =
Arc<dyn Fn(&Evaluator, &ast::LambdaExpr, &ValueRef, &ValueRef) -> ValueRef>;

/// Proxy functions represent the saved functions of the runtime itself,
/// rather than executing KCL defined functions or plugin functions.
#[derive(Clone)]
pub struct FunctionProxy {
lambda_expr: ast::LambdaExpr,
inner: FunctionHandler,
}

impl Debug for FunctionProxy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let ptr_value = Arc::as_ptr(&self.inner);
f.debug_struct("FunctionProxy")
.field("inner", &format!("{ptr_value:p}"))
.finish()
}
}

impl FunctionProxy {
#[inline]
pub fn new(lambda_expr: ast::LambdaExpr, proxy: FunctionHandler) -> Self {
Self {
lambda_expr,
inner: proxy,
}
}
}

impl<'ctx> Evaluator<'ctx> {
#[inline]
pub(crate) fn invoke_proxy_function(
&self,
proxy_index: Index,
args: &ValueRef,
kwargs: &ValueRef,
) -> ValueRef {
let proxy = {
let functions = self.functions.borrow();
functions
.get(proxy_index)
.expect(kcl_error::INTERNAL_ERROR_MSG)
.clone()
};
(proxy.inner)(self, &proxy.lambda_expr, args, kwargs)
}
}
15 changes: 0 additions & 15 deletions kclvm/evaluator/src/function.rs

This file was deleted.

36 changes: 22 additions & 14 deletions kclvm/evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod tests;
pub(crate) mod calculation;
pub(crate) mod context;
pub(crate) mod error;
pub(crate) mod function;
pub(crate) mod func;
pub(crate) mod module;
pub(crate) mod node;
pub(crate) mod scope;
Expand All @@ -15,9 +15,10 @@ pub(crate) mod value;
extern crate kclvm_error;

use context::EvaluatorContext;
use kclvm_ast::walker::TypedResultWalker;
use std::cell::RefCell;
use func::FunctionProxy;
use generational_arena::Arena;
use std::str;
use std::{cell::RefCell, sync::Arc};

use crate::error as kcl_error;
use anyhow::Result;
Expand All @@ -39,28 +40,35 @@ pub struct Evaluator<'ctx> {
pub program: &'ctx ast::Program,
pub ctx: RefCell<EvaluatorContext>,
pub runtime_ctx: RefCell<Context>,
pub functions: RefCell<Arena<Arc<FunctionProxy>>>,
}

impl<'ctx> Evaluator<'ctx> {
/// New aa Evaluator using the LLVM Context and AST Program
/// New aa Evaluator using the AST program
#[inline]
pub fn new(program: &'ctx ast::Program) -> Evaluator<'ctx> {
Self::new_with_runtime_ctx(program, Context::new())
}

/// New aa Evaluator using the AST program and runtime context
#[inline]
pub fn new_with_runtime_ctx(
program: &'ctx ast::Program,
runtime_ctx: Context,
) -> Evaluator<'ctx> {
Evaluator {
ctx: RefCell::new(EvaluatorContext::default()),
runtime_ctx: RefCell::new(Context::new()),
runtime_ctx: RefCell::new(runtime_ctx),
program,
functions: RefCell::new(Arena::new()),
}
}

/// Generate LLVM IR of ast module.
/// Evaluate the program
pub fn run(self: &Evaluator<'ctx>) -> Result<(String, String)> {
self.init_scope(kclvm_ast::MAIN_PKG);
for module in self
.program
.pkgs
.get(kclvm_ast::MAIN_PKG)
.unwrap_or(&vec![])
{
self.walk_module(module)?;
if let Some(modules) = self.program.pkgs.get(kclvm_ast::MAIN_PKG) {
self.init_scope(kclvm_ast::MAIN_PKG);
self.compile_ast_modules(modules)
}
Ok(self.plan_globals_to_string())
}
Expand Down
Loading
Loading