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: add literal type default value pass and preprocess #1583

Merged
merged 1 commit into from
Aug 19, 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
10 changes: 4 additions & 6 deletions kclvm/ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1347,15 +1347,13 @@ pub struct StringLit {
}

/// Generate ast.StringLit from String
impl TryFrom<String> for StringLit {
type Error = &'static str;

fn try_from(value: String) -> Result<Self, Self::Error> {
Ok(Self {
impl From<String> for StringLit {
fn from(value: String) -> Self {
Self {
value: value.clone(),
raw_value: format!("{:?}", value),
is_long_string: false,
})
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions kclvm/sema/src/pre_process/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for ConfigNestAttrTransformer {
}
}

#[derive(Debug)]
#[derive(Debug, Default)]
struct ConfigMergeTransformer {}

#[derive(Debug)]
Expand Down Expand Up @@ -355,9 +355,10 @@ fn unify_config_entries(
entries
}

/// Merge program
/// Merge program for multiple file config.
#[inline]
pub fn merge_program(program: &mut ast::Program) {
let mut merger = ConfigMergeTransformer {};
let mut merger = ConfigMergeTransformer::default();
merger.merge(program);
}

Expand Down
1 change: 1 addition & 0 deletions kclvm/sema/src/pre_process/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ pub fn fix_qualified_identifier<'ctx>(
}

/// Fix AST raw identifier prefix `$`, e.g., $filter -> filter
#[inline]
pub fn fix_raw_identifier_prefix(module: &'_ mut ast::Module) {
RawIdentifierTransformer::default().walk_module(module);
}
89 changes: 89 additions & 0 deletions kclvm/sema/src/pre_process/lit_ty_default_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use kclvm_ast::ast;
use kclvm_ast::walker::MutSelfMutWalker;

#[derive(Default)]
struct LitTypeDefaultValueTransformer;

impl<'ctx> MutSelfMutWalker<'ctx> for LitTypeDefaultValueTransformer {
fn walk_schema_attr(&mut self, schema_attr: &'ctx mut ast::SchemaAttr) {
if schema_attr.value.is_none() && !schema_attr.is_optional {
if let ast::Type::Literal(literal_ty) = &schema_attr.ty.node {
let filename = schema_attr.ty.filename.clone();
let line = schema_attr.ty.end_line;
// Append ` = ` width for th column.
let column = schema_attr.ty.end_column + 3;
schema_attr.op = Some(ast::AugOp::Assign);
match literal_ty {
ast::LiteralType::Bool(val) => {
let column_offset = if *val { 4 } else { 5 };
schema_attr.value = Some(Box::new(ast::Node::new(
ast::Expr::NameConstantLit(ast::NameConstantLit {
value: if *val {
ast::NameConstant::True
} else {
ast::NameConstant::False
},
}),
filename,
line,
column,
line,
column + column_offset,
)));
}
ast::LiteralType::Int(val) => {
let value = val.value.to_string();
let mut column_offset = value.len() as u64;
if let Some(suffix) = &val.suffix {
column_offset += suffix.value().len() as u64
}
schema_attr.value = Some(Box::new(ast::Node::new(
ast::Expr::NumberLit(ast::NumberLit {
binary_suffix: val.suffix.clone(),
value: ast::NumberLitValue::Int(val.value),
}),
filename,
line,
column,
line,
column + column_offset,
)));
}
ast::LiteralType::Float(val) => {
let value = kclvm_runtime::float_to_string(*val);
let column_offset = value.len() as u64;
schema_attr.value = Some(Box::new(ast::Node::new(
ast::Expr::NumberLit(ast::NumberLit {
binary_suffix: None,
value: ast::NumberLitValue::Float(*val),
}),
filename,
line,
column,
line,
column + column_offset,
)));
}
ast::LiteralType::Str(val) => {
let value: ast::StringLit = val.to_string().into();
let column_offset = value.raw_value.len() as u64;
schema_attr.value = Some(Box::new(ast::Node::new(
ast::Expr::StringLit(value),
filename,
line,
column,
line,
column + column_offset,
)));
}
}
}
}
}
}

/// Fix literal type default value. e.g., `a: "value"` -> `a: "value" = "value"`.
#[inline]
pub fn fix_lit_ty_default_value(module: &'_ mut ast::Module) {
LitTypeDefaultValueTransformer::default().walk_module(module);
}
3 changes: 3 additions & 0 deletions kclvm/sema/src/pre_process/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod config;
mod identifier;
mod lit_ty_default_value;
mod multi_assign;

use indexmap::IndexMap;
Expand All @@ -10,6 +11,7 @@ mod tests;

pub use config::{fix_config_expr_nest_attr, merge_program};
pub use identifier::{fix_qualified_identifier, fix_raw_identifier_prefix};
pub use lit_ty_default_value::fix_lit_ty_default_value;
pub use multi_assign::transform_multi_assign;

use crate::resolver::Options;
Expand All @@ -36,6 +38,7 @@ pub fn pre_process_program(program: &mut ast::Program, opts: &Options) {
fix_raw_identifier_prefix(module);
fix_qualified_identifier(module, &mut import_names);
fix_config_expr_nest_attr(module);
fix_lit_ty_default_value(module);
}
}
if opts.merge_program {
Expand Down
7 changes: 7 additions & 0 deletions kclvm/sema/src/pre_process/test_data/lit_ty_default_val.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
schema LitTyConfig:
val0: "val"
val1: 1
val2: 1Ki
val3: 2.0
val4: True
val5: False
76 changes: 76 additions & 0 deletions kclvm/sema/src/pre_process/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,82 @@ fn test_fix_qualified_identifier() {
}
}

#[test]
fn test_fix_lit_ty_default_value() {
let mut module =
parse_file_force_errors("./src/pre_process/test_data/lit_ty_default_val.k", None).unwrap();
fix_lit_ty_default_value(&mut module);
if let ast::Stmt::Schema(schema_stmt) = &module.body[0].node {
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[0].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::StringLit(ast::StringLit {
is_long_string: false,
raw_value: "\"val\"".to_string(),
value: "val".to_string(),
})
)
} else {
panic!("invalid schema attr value")
}
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[1].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::NumberLit(ast::NumberLit {
value: ast::NumberLitValue::Int(1),
binary_suffix: None,
})
)
} else {
panic!("invalid schema attr value")
}
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[2].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::NumberLit(ast::NumberLit {
value: ast::NumberLitValue::Int(1),
binary_suffix: Some(ast::NumberBinarySuffix::Ki),
})
)
} else {
panic!("invalid schema attr value")
}
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[3].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::NumberLit(ast::NumberLit {
value: ast::NumberLitValue::Float(2.0),
binary_suffix: None,
})
)
} else {
panic!("invalid schema attr value")
}
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[4].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::NameConstantLit(ast::NameConstantLit {
value: ast::NameConstant::True,
})
)
} else {
panic!("invalid schema attr value")
}
if let ast::Stmt::SchemaAttr(schema_attr) = &schema_stmt.body[5].node {
assert_eq!(
schema_attr.value.as_ref().unwrap().node,
ast::Expr::NameConstantLit(ast::NameConstantLit {
value: ast::NameConstant::False,
})
)
} else {
panic!("invalid schema attr value")
}
} else {
panic!("invalid schema statement")
}
}

#[test]
fn test_fix_raw_identifier_prefix() {
let mut module =
Expand Down
8 changes: 7 additions & 1 deletion kclvm/sema/src/resolver/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,13 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> {
None,
),
},
None => bug!("invalid ast schema attr op kind"),
// Default is Assign
None => self.must_assignable_to(
value_ty,
expected_ty,
schema_attr.name.get_span_pos(),
None,
),
}
}
self.any_ty()
Expand Down
9 changes: 9 additions & 0 deletions test/grammar/schema/default_value/default_value_3/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
schema Config:
val0: "val"
val1: 1
val2: 1Ki
val3: 2.0
val4: True
val5: False

c = Config {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
c:
val0: val
val1: 1
val2: 1024.0
val3: 2.0
val4: true
val5: false
Loading