Skip to content

Commit

Permalink
feat: add decorator results in the schema type API. (#643)
Browse files Browse the repository at this point in the history
  • Loading branch information
Peefy authored Aug 8, 2023
1 parent 327cb1e commit 115b71b
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 19 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.

4 changes: 3 additions & 1 deletion kclvm/api/src/service/capi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub unsafe extern "C" fn kclvm_service_delete(serv: *mut kclvm_service) {
#[no_mangle]
pub unsafe extern "C" fn kclvm_service_free_string(res: *mut c_char) {
if !res.is_null() {
unsafe { CString::from_raw(res) };
unsafe {
let _ = CString::from_raw(res);
};
}
}

Expand Down
12 changes: 11 additions & 1 deletion kclvm/api/src/service/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pub(crate) fn kcl_schema_ty_to_pb_ty(schema_ty: &SchemaType) -> KclType {
.iter()
.map(|d| Decorator {
name: d.name.clone(),
..Default::default()
arguments: d.arguments.clone(),
keywords: d.keywords.clone(),
})
.collect(),
filename: schema_ty.filename.clone(),
Expand All @@ -66,6 +67,15 @@ fn get_schema_ty_attributes(schema_ty: &SchemaType, line: &mut i32) -> HashMap<S
let mut ty = kcl_ty_to_pb_ty(&attr.ty);
ty.line = *line;
ty.description = attr.doc.clone().unwrap_or_default();
ty.decorators = attr
.decorators
.iter()
.map(|d| Decorator {
name: d.name.clone(),
arguments: d.arguments.clone(),
keywords: d.keywords.clone(),
})
.collect();
type_mapping.insert(key.to_string(), ty);
*line += 1
}
Expand Down
2 changes: 1 addition & 1 deletion kclvm/api/src/testdata/get-schema-type-mapping.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"file": "schema.k",
"code": "schema Server:\n \"\"\"Server is the common user interface for long-running\n services adopting the best practice of Kubernetes.\n\n Attributes\n ----------\n workloadType: str, default is \"Deployment\", required\n Use this attribute to specify which kind of long-running service you want.\n Valid values: Deployment, CafeDeployment.\n See also: kusion_models/core/v1/workload_metadata.k.\n name: str, required\n A Server-level attribute.\n The name of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n labels: {str:str}, optional\n A Server-level attribute.\n The labels of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n\n Examples\n ----------------------\n myCustomApp = AppConfiguration {\n name = \"componentName\"\n }\n \"\"\"\n workloadType: str = \"Deployment\"\n name: str\n labels?: {str:str}\n containers: [Container]\n\nschema Container:\n \"\"\"Container is the common user interface for long-running services.\n\n Attributes\n ----------\n name: str, required\n The name of the long-running container.\n \"\"\"\n name: str\n"
"code": "@info(name=\"ServerSchema\")\nschema Server:\n \"\"\"Server is the common user interface for long-running\n services adopting the best practice of Kubernetes.\n\n Attributes\n ----------\n workloadType: str, default is \"Deployment\", required\n Use this attribute to specify which kind of long-running service you want.\n Valid values: Deployment, CafeDeployment.\n See also: kusion_models/core/v1/workload_metadata.k.\n name: str, required\n A Server-level attribute.\n The name of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n labels: {str:str}, optional\n A Server-level attribute.\n The labels of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n\n Examples\n ----------------------\n myCustomApp = AppConfiguration {\n name = \"componentName\"\n }\n \"\"\"\n workloadType: str = \"Deployment\"\n @info(\"name\", key=\"value\")\n name: str\n labels?: {str:str}\n containers: [Container]\n\nschema Container:\n \"\"\"Container is the common user interface for long-running services.\n\n Attributes\n ----------\n name: str, required\n The name of the long-running container.\n \"\"\"\n name: str\n"
}
22 changes: 20 additions & 2 deletions kclvm/api/src/testdata/get-schema-type-mapping.response.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,17 @@
"properties": {},
"required": [],
"line": 2,
"decorators": [],
"decorators": [
{
"name": "info",
"arguments": [
"\"name\""
],
"keywords": {
"key": "\"value\""
}
}
],
"filename": "",
"pkg_path": "",
"description": "A Server-level attribute.\nThe name of the long-running service.\nSee also: kusion_models/core/v1/metadata.k.",
Expand Down Expand Up @@ -137,7 +147,15 @@
"containers"
],
"line": 0,
"decorators": [],
"decorators": [
{
"name": "info",
"arguments": [],
"keywords": {
"name": "\"ServerSchema\""
}
}
],
"filename": "schema.k",
"pkg_path": "__main__",
"description": "Server is the common user interface for long-running services adopting the best practice of Kubernetes.",
Expand Down
2 changes: 1 addition & 1 deletion kclvm/ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub use TokenKind::*;
pub use UnaryOpToken::*;

use compiler_base_span::{Span, DUMMY_SP};
use kclvm_span::symbol::{Ident, Symbol};
pub use kclvm_span::symbol::{Ident, Symbol};

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum CommentKind {
Expand Down
4 changes: 3 additions & 1 deletion kclvm/ast_pretty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
kclvm-parser = {path = "../parser"}
kclvm-error = {path = "../error"}
kclvm-ast = {path = "../ast"}

Expand All @@ -15,3 +14,6 @@ fancy-regex = "0.7.1"
pretty_assertions = "1.3.0"
compiler_base_session = {path = "../../compiler_base/session"}
compiler_base_macros = "0.0.1"

[dev-dependencies]
kclvm-parser = {path = "../parser"}
6 changes: 4 additions & 2 deletions kclvm/sema/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ unicode_names2 = "0.4"
petgraph = "0.6.0"
anyhow = "1.0"
regex = "1.7.0"
lazy_static = "1.4.0"
pcre2 = "*"

kclvm-ast = {path = "../ast"}
kclvm-ast-pretty = {path = "../ast_pretty"}
kclvm-runtime = {path = "../runtime"}
kclvm-error = {path = "../error"}
kclvm-span = {path = "../span"}
compiler_base_span = {path = "../../compiler_base/span", version = "0.0.2"}
compiler_base_session = {path = "../../compiler_base/session"}
compiler_base_macros = "0.0.1"
compiler_base_error = "0.0.8"
lazy_static = "1.4.0"
pcre2 = "*"

[dev-dependencies]
kclvm-parser = {path = "../parser"}
Expand Down
13 changes: 11 additions & 2 deletions kclvm/sema/src/resolver/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,11 +589,12 @@ impl<'ctx> Resolver<'ctx> {
column: pos.column,
},
doc: None,
decorators: vec![],
},
);
let parsed_doc = parse_doc_string(&schema_stmt.doc);
for stmt in &schema_stmt.body {
let (name, ty, is_optional, has_default) = match &stmt.node {
let (name, ty, is_optional, has_default, decorators) = match &stmt.node {
ast::Stmt::Unification(unification_stmt) => {
let name = unification_stmt.value.node.name.node.get_name();
let ty = self.parse_ty_str_with_scope(&name, stmt.get_span_pos());
Expand All @@ -604,6 +605,7 @@ impl<'ctx> Resolver<'ctx> {
ty,
is_optional,
has_default,
vec![],
)
}
ast::Stmt::SchemaAttr(schema_attr) => {
Expand All @@ -614,7 +616,13 @@ impl<'ctx> Resolver<'ctx> {
);
let is_optional = schema_attr.is_optional;
let has_default = schema_attr.value.is_some();
(name, ty, is_optional, has_default)
// Schema attribute decorators
let decorators = self.resolve_decorators(
&schema_attr.decorators,
DecoratorTarget::Attribute,
&name,
);
(name, ty, is_optional, has_default, decorators)
}
_ => continue,
};
Expand All @@ -639,6 +647,7 @@ impl<'ctx> Resolver<'ctx> {
ty: ty.clone(),
pos: pos.clone(),
doc: doc_str,
decorators,
},
);
}
Expand Down
6 changes: 1 addition & 5 deletions kclvm/sema/src/resolver/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use kclvm_error::*;
use std::rc::Rc;

use crate::info::is_private_field;
use crate::ty::{
sup, DecoratorTarget, Parameter, Type, TypeInferMethods, TypeKind, RESERVED_TYPE_IDENTIFIERS,
};
use crate::ty::{sup, Parameter, Type, TypeInferMethods, TypeKind, RESERVED_TYPE_IDENTIFIERS};

use super::format::VALID_FORMAT_SPEC_SET;
use super::scope::{ScopeKind, ScopeObject, ScopeObjectKind};
Expand Down Expand Up @@ -367,8 +365,6 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> {
.map(|attr| attr.doc.clone())
.flatten();

// Schema attribute decorators
self.resolve_decorators(&schema_attr.decorators, DecoratorTarget::Attribute, name);
self.insert_object(
name,
ScopeObject {
Expand Down
33 changes: 33 additions & 0 deletions kclvm/sema/src/resolver/schema.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use crate::builtin::BUILTIN_DECORATORS;
Expand All @@ -7,6 +8,7 @@ use crate::ty::{Decorator, DecoratorTarget, TypeKind};
use kclvm_ast::ast;
use kclvm_ast::pos::GetPos;
use kclvm_ast::walker::MutSelfTypedResultWalker;
use kclvm_ast_pretty::{print_ast_node, ASTNode};
use kclvm_error::{ErrorKind, Message, Position, Style};

use super::node::ResolvedResult;
Expand Down Expand Up @@ -183,10 +185,16 @@ impl<'ctx> Resolver<'ctx> {
&decorator.node.keywords,
&func_ty.params,
);
let (arguments, keywords) = self.arguments_to_string(
&decorator.node.args,
&decorator.node.keywords,
);
decorator_objs.push(Decorator {
target: target.clone(),
name,
key: key.to_string(),
arguments,
keywords,
})
}
_ => bug!("invalid builtin decorator function type"),
Expand All @@ -208,4 +216,29 @@ impl<'ctx> Resolver<'ctx> {
}
decorator_objs
}

fn arguments_to_string(
&mut self,
args: &'ctx [ast::NodeRef<ast::Expr>],
kwargs: &'ctx [ast::NodeRef<ast::Keyword>],
) -> (Vec<String>, HashMap<String, String>) {
(
args.iter()
.map(|a| print_ast_node(ASTNode::Expr(a)))
.collect(),
kwargs
.iter()
.map(|a| {
(
a.node.arg.node.get_name(),
a.node
.value
.as_ref()
.map(|v| print_ast_node(ASTNode::Expr(v)))
.unwrap_or_default(),
)
})
.collect(),
)
}
}
13 changes: 10 additions & 3 deletions kclvm/sema/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ pub mod parser;
mod unify;
mod walker;

use std::collections::HashMap;
use std::rc::Rc;

pub use constants::*;
pub use context::{TypeContext, TypeInferMethods};
use indexmap::IndexMap;
use kclvm_ast::ast;
use kclvm_ast::MAIN_PKG;
use kclvm_error::Position;
pub use unify::*;
pub use walker::walk_type;

use indexmap::IndexMap;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -209,6 +209,7 @@ impl SchemaType {
ty,
pos: Position::dummy_pos(),
doc: None,
decorators: vec![],
};
self.attrs.insert(attr.to_string(), schema_attr);
}
Expand Down Expand Up @@ -253,6 +254,7 @@ pub struct SchemaAttr {
pub ty: Rc<Type>,
pub pos: Position,
pub doc: Option<String>,
pub decorators: Vec<Decorator>,
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -294,11 +296,16 @@ pub enum ModuleKind {

#[derive(Debug, Clone, PartialEq)]
pub struct Decorator {
/// The decorator target e.g., the schema statement or schema attribute.
pub target: DecoratorTarget,
/// The decorator name.
pub name: String,
/// The schema or attribute name of decorator dimension
/// The schema or attribute name of decorator dimension.
pub key: String,
/// The decorator argument list values.
pub arguments: Vec<String>,
/// The decorator keyword mapping values.
pub keywords: HashMap<String, String>,
}

#[derive(Debug, Clone, PartialEq)]
Expand Down

0 comments on commit 115b71b

Please sign in to comment.