Skip to content

Commit

Permalink
feat: impl runtime.catch function
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <[email protected]>
  • Loading branch information
Peefy committed Jul 1, 2024
1 parent 8d766a1 commit f688c4f
Show file tree
Hide file tree
Showing 38 changed files with 432 additions and 151 deletions.
1 change: 1 addition & 0 deletions kclvm/Cargo.lock

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

6 changes: 3 additions & 3 deletions kclvm/api/src/service/service_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ impl KclvmServiceImpl {
/// assert_eq!(result.type_errors.len(), 0);
/// assert_eq!(result.symbols.len(), 12);
/// assert_eq!(result.scopes.len(), 3);
/// assert_eq!(result.node_symbol_map.len(), 177);
/// assert_eq!(result.symbol_node_map.len(), 177);
/// assert_eq!(result.fully_qualified_name_map.len(), 186);
/// assert_eq!(result.node_symbol_map.len(), 178);
/// assert_eq!(result.symbol_node_map.len(), 178);
/// assert_eq!(result.fully_qualified_name_map.len(), 188);
/// assert_eq!(result.pkg_scope_map.len(), 3);
/// ```
#[inline]
Expand Down
1 change: 1 addition & 0 deletions kclvm/evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ kclvm-ast = {path = "../ast"}
kclvm-sema = {path = "../sema"}
kclvm-runtime = {path = "../runtime"}
kclvm-error = {path = "../error"}
scopeguard = "1.2.0"

[dev-dependencies]
kclvm-parser = {path = "../parser"}
Expand Down
15 changes: 10 additions & 5 deletions kclvm/evaluator/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use generational_arena::Index;
use indexmap::IndexMap;
use kclvm_ast::ast;
use kclvm_runtime::ValueRef;
use scopeguard::defer;

use crate::proxy::Proxy;
use crate::Evaluator;
Expand Down Expand Up @@ -75,6 +76,12 @@ impl<'ctx> Evaluator<'ctx> {
self.push_pkgpath(&frame.pkgpath);
// Change the backtrace metadata: filename, line, etc.
self.push_backtrace(&frame);
defer! {
// Recover the backtrace metadata: filename, line, etc.
self.pop_backtrace();
// Recover the package path scope.
self.pop_pkgpath();
}
let value = match &frame.proxy {
// Call a function and return the value
Proxy::Lambda(lambda) => {
Expand All @@ -101,10 +108,6 @@ impl<'ctx> Evaluator<'ctx> {
// The built-in lazy eval semantics prevent invoking
Proxy::Global(_) => self.undefined_value(),
};
// Recover the backtrace metadata: filename, line, etc.
self.pop_backtrace();
// Recover the package path scope.
self.pop_pkgpath();
value
}
}
Expand All @@ -117,11 +120,13 @@ pub fn func_body(
kwargs: &ValueRef,
) -> ValueRef {
s.enter_scope();
defer! {
s.leave_scope();
}
// Evaluate arguments and keyword arguments and store values to local variables.
s.walk_arguments(&ctx.node.args, args, kwargs);
let result = s
.walk_stmts(&ctx.node.body)
.expect(kcl_error::RUNTIME_ERROR_MSG);
s.leave_scope();
result
}
1 change: 1 addition & 0 deletions kclvm/evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod module;
mod node;
mod proxy;
mod rule;
mod runtime;
mod schema;
mod scope;
mod ty;
Expand Down
59 changes: 34 additions & 25 deletions kclvm/evaluator/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ use anyhow::Ok;
use generational_arena::Index;
use kclvm_ast::ast::{self, CallExpr, ConfigEntry, NodeRef};
use kclvm_ast::walker::TypedResultWalker;
use kclvm_runtime::val_func::invoke_function;
use kclvm_runtime::{
schema_assert, schema_runtime_type, ConfigEntryOperationKind, DecoratorValue, RuntimeErrorType,
UnionOptions, ValueRef, PKG_PATH_PREFIX,
};
use kclvm_sema::{builtin, pkgpath_without_prefix, plugin};
use scopeguard::defer;

use crate::error::INTERNAL_ERROR_MSG;
use crate::func::{func_body, FunctionCaller, FunctionEvalContext};
use crate::lazy::Setter;
use crate::proxy::Proxy;
use crate::rule::{rule_body, rule_check, RuleCaller, RuleEvalContext};
use crate::runtime::invoke_function;
use crate::schema::{schema_body, schema_check, SchemaCaller, SchemaEvalContext};
use crate::ty::type_pack_and_check;
use crate::union::union_entry;
Expand Down Expand Up @@ -391,6 +392,10 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
let mut iter_value = iter_host_value.iter();
// Start iteration and enter the loop scope for the loop variable.
self.enter_scope();
defer! {
self.leave_scope();
self.clear_local_vars();
}
// Start block
while let Some((next_value, key, value)) = iter_value.next_with_key_value(&iter_host_value)
{
Expand Down Expand Up @@ -439,15 +444,11 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
match quant_expr.op {
ast::QuantOperation::All => {
if !is_truth {
self.leave_scope();
self.clear_local_vars();
return Ok(self.bool_value(false));
}
}
ast::QuantOperation::Any => {
if is_truth {
self.leave_scope();
self.clear_local_vars();
return Ok(self.bool_value(true));
}
}
Expand All @@ -467,8 +468,6 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
}
}
}
self.leave_scope();
self.clear_local_vars();
// End for block.
Ok(result)
}
Expand Down Expand Up @@ -696,13 +695,8 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
// Invoke user defined functions, schemas or rules.
Ok(self.invoke_proxy_function(proxy, &list_value, &dict_value))
} else {
// Invoke builtin function or plugin functions.
Ok(invoke_function(
&func,
&mut list_value,
&dict_value,
&mut self.runtime_ctx.borrow_mut(),
))
// Invoke runtime builtin functions or external plugin functions.
Ok(invoke_function(self, &func, &mut list_value, &dict_value))
};
self.set_local_vars(vars);
result
Expand Down Expand Up @@ -800,6 +794,9 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
fn walk_list_comp(&self, list_comp: &'ctx ast::ListComp) -> Self::Result {
let mut collection_value = self.list_value();
self.enter_scope();
defer! {
self.leave_scope();
}
self.walk_generator(
&list_comp.generators,
&list_comp.elt,
Expand All @@ -809,13 +806,15 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
&mut collection_value,
&ast::CompType::List,
);
self.leave_scope();
Ok(collection_value)
}

fn walk_dict_comp(&self, dict_comp: &'ctx ast::DictComp) -> Self::Result {
let mut collection_value = self.dict_value();
self.enter_scope();
defer! {
self.leave_scope();
}
let key = dict_comp
.entry
.key
Expand All @@ -830,7 +829,7 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
&mut collection_value,
&ast::CompType::Dict,
);
self.leave_scope();

Ok(collection_value)
}

Expand Down Expand Up @@ -863,6 +862,9 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
// Check the required attributes only when the values of all attributes
// in the final schema are solved.
self.push_schema_expr();
defer! {
self.pop_schema_expr();
}
let config_value = self.walk_expr(&schema_expr.config)?;
let schema_type = self.walk_identifier_with_ctx(
&schema_expr.name.node,
Expand Down Expand Up @@ -900,26 +902,30 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
if let Proxy::Schema(schema) = &frame.proxy {
self.push_pkgpath(&frame.pkgpath);
self.push_backtrace(&frame);
defer! {
self.pop_backtrace();
self.pop_pkgpath();
}
let value = (schema.body)(
self,
&schema.ctx.borrow().snapshot(config_value, config_meta),
&list_value,
&dict_value,
);
self.pop_backtrace();
self.pop_pkgpath();
value
} else if let Proxy::Rule(rule) = &frame.proxy {
self.push_pkgpath(&frame.pkgpath);
self.push_backtrace(&frame);
defer! {
self.pop_backtrace();
self.pop_pkgpath();
}
let value = (rule.body)(
self,
&rule.ctx.borrow().snapshot(config_value, config_meta),
&list_value,
&dict_value,
);
self.pop_backtrace();
self.pop_pkgpath();
value
} else {
self.undefined_value()
Expand All @@ -933,15 +939,16 @@ impl<'ctx> TypedResultWalker<'ctx> for Evaluator<'ctx> {
&UnionOptions::default(),
)
};
self.pop_schema_expr();
Ok(schema)
}

#[inline]
fn walk_config_expr(&self, config_expr: &'ctx ast::ConfigExpr) -> Self::Result {
self.enter_scope();
defer! {
self.leave_scope();
}
let result = self.walk_config_entries(&config_expr.items);
self.leave_scope();
result
}

Expand Down Expand Up @@ -1200,10 +1207,12 @@ impl<'ctx> Evaluator<'ctx> {
self.push_pkgpath(&frame.pkgpath);
self.enter_scope();
self.push_backtrack_meta(setter);
defer! {
self.pop_backtrack_meta();
self.leave_scope();
self.pop_pkgpath();
}
let value = self.walk_stmt(stmt);
self.pop_backtrack_meta();
self.leave_scope();
self.pop_pkgpath();
value
} else {
self.ok_result()
Expand Down
25 changes: 17 additions & 8 deletions kclvm/evaluator/src/proxy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use kclvm_runtime::ValueRef;
use scopeguard::defer;

use crate::error as kcl_error;
use crate::func::FunctionCaller;
Expand Down Expand Up @@ -55,12 +56,14 @@ pub(crate) fn call_schema_body(
if let Proxy::Schema(schema) = &frame.proxy {
s.push_pkgpath(&frame.pkgpath);
s.push_backtrace(&frame);
defer! {
s.pop_backtrace();
s.pop_pkgpath();
}
{
schema.ctx.borrow_mut().set_info_with_schema(&ctx.borrow())
}
let value = (schema.body)(s, &schema.ctx, args, kwargs);
s.pop_backtrace();
s.pop_pkgpath();
value
} else {
ctx.borrow().value.clone()
Expand Down Expand Up @@ -89,12 +92,14 @@ pub(crate) fn call_schema_body_from_rule(
if let Proxy::Schema(schema) = &frame.proxy {
s.push_pkgpath(&frame.pkgpath);
s.push_backtrace(&frame);
defer! {
s.pop_backtrace();
s.pop_pkgpath();
}
{
schema.ctx.borrow_mut().set_info_with_rule(&ctx.borrow())
}
let value = (schema.body)(s, &schema.ctx, args, kwargs);
s.pop_backtrace();
s.pop_pkgpath();
value
} else {
ctx.borrow().value.clone()
Expand Down Expand Up @@ -123,12 +128,14 @@ pub(crate) fn call_schema_check(
if let Proxy::Schema(schema) = &frame.proxy {
s.push_pkgpath(&frame.pkgpath);
s.push_backtrace(&frame);
defer! {
s.pop_backtrace();
s.pop_pkgpath();
}
if let Some(ctx) = ctx {
schema.ctx.borrow_mut().set_info_with_schema(&ctx.borrow())
}
(schema.check)(s, &schema.ctx, schema_value, args, kwargs);
s.pop_backtrace();
s.pop_pkgpath();
}
}
}
Expand All @@ -145,9 +152,11 @@ pub(crate) fn call_rule_check(s: &Evaluator, func: &ValueRef, args: &ValueRef, k
if let Proxy::Rule(rule) = &frame.proxy {
s.push_pkgpath(&frame.pkgpath);
s.push_backtrace(&frame);
defer! {
s.pop_backtrace();
s.pop_pkgpath();
}
(rule.check)(s, &rule.ctx, args, kwargs);
s.pop_backtrace();
s.pop_pkgpath();
}
}
}
7 changes: 5 additions & 2 deletions kclvm/evaluator/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::Arc;
use kclvm_ast::ast;
use kclvm_ast::walker::TypedResultWalker;
use kclvm_runtime::ValueRef;
use scopeguard::defer;

use crate::error as kcl_error;
use crate::lazy::LazyEvalScope;
Expand Down Expand Up @@ -95,6 +96,10 @@ pub fn rule_body(
let rule_name = &ctx.borrow().node.name.node;
s.push_schema(crate::EvalContext::Rule(ctx.clone()));
s.enter_scope();
defer! {
s.leave_scope();
s.pop_schema();
}
// Evaluate arguments and keyword arguments and store values to local variables.
s.walk_arguments(&ctx.borrow().node.args, args, kwargs);
// Eval schema body and record schema instances.
Expand All @@ -110,8 +115,6 @@ pub fn rule_body(
// Call rule check block function
rule_check(s, ctx, args, kwargs);
}
s.leave_scope();
s.pop_schema();
rule_value
}

Expand Down
Loading

0 comments on commit f688c4f

Please sign in to comment.