diff --git a/kclvm/api/src/service/service_impl.rs b/kclvm/api/src/service/service_impl.rs index 12f588821..5b539aa80 100644 --- a/kclvm/api/src/service/service_impl.rs +++ b/kclvm/api/src/service/service_impl.rs @@ -172,9 +172,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(), 159); - /// assert_eq!(result.symbol_node_map.len(), 159); - /// assert_eq!(result.fully_qualified_name_map.len(), 166); + /// assert_eq!(result.node_symbol_map.len(), 160); + /// assert_eq!(result.symbol_node_map.len(), 160); + /// assert_eq!(result.fully_qualified_name_map.len(), 168); /// assert_eq!(result.pkg_scope_map.len(), 3); /// ``` pub fn load_package(&self, args: &LoadPackageArgs) -> anyhow::Result { diff --git a/kclvm/runtime/src/_kclvm.bc b/kclvm/runtime/src/_kclvm.bc index 1ad2df9c5..2fb0f1688 100644 Binary files a/kclvm/runtime/src/_kclvm.bc and b/kclvm/runtime/src/_kclvm.bc differ diff --git a/kclvm/runtime/src/_kclvm.h b/kclvm/runtime/src/_kclvm.h index 0cdfe40eb..dc2c004f0 100644 --- a/kclvm/runtime/src/_kclvm.h +++ b/kclvm/runtime/src/_kclvm.h @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -300,6 +300,8 @@ void kclvm_dict_update_key_value(kclvm_value_ref_t* p, kclvm_value_ref_t* key, k kclvm_value_ref_t* kclvm_dict_values(kclvm_context_t* ctx, kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_file_read(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); + kclvm_value_ref_t* kclvm_iterator_cur_key(kclvm_iterator_t* p); kclvm_value_ref_t* kclvm_iterator_cur_value(kclvm_iterator_t* p); diff --git a/kclvm/runtime/src/_kclvm.ll b/kclvm/runtime/src/_kclvm.ll index 509be3a9c..2269d92bb 100644 --- a/kclvm/runtime/src/_kclvm.ll +++ b/kclvm/runtime/src/_kclvm.ll @@ -1,4 +1,4 @@ -; Copyright 2021 The KCL Authors. All rights reserved. +; Copyright The KCL Authors. All rights reserved. ; Auto generated, DONOT EDIT!!! @@ -248,6 +248,8 @@ declare void @kclvm_dict_update_key_value(%kclvm_value_ref_t* %p, %kclvm_value_r declare %kclvm_value_ref_t* @kclvm_dict_values(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_file_read(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + declare %kclvm_value_ref_t* @kclvm_iterator_cur_key(%kclvm_iterator_t* %p); declare %kclvm_value_ref_t* @kclvm_iterator_cur_value(%kclvm_iterator_t* %p); diff --git a/kclvm/runtime/src/_kclvm.rs b/kclvm/runtime/src/_kclvm.rs index 2b46c3eb0..f3ae033af 100644 --- a/kclvm/runtime/src/_kclvm.rs +++ b/kclvm/runtime/src/_kclvm.rs @@ -1,4 +1,4 @@ -//! Copyright The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -136,6 +136,7 @@ pub enum ApiFunc { kclvm_dict_update, kclvm_dict_update_key_value, kclvm_dict_values, + kclvm_file_read, kclvm_iterator_cur_key, kclvm_iterator_cur_value, kclvm_iterator_delete, diff --git a/kclvm/runtime/src/_kclvm_addr.rs b/kclvm/runtime/src/_kclvm_addr.rs index 450bd44c5..813f83af8 100644 --- a/kclvm/runtime/src/_kclvm_addr.rs +++ b/kclvm/runtime/src/_kclvm_addr.rs @@ -1,4 +1,4 @@ -//! Copyright The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -143,6 +143,7 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_dict_update" => crate::kclvm_dict_update as *const () as u64, "kclvm_dict_update_key_value" => crate::kclvm_dict_update_key_value as *const () as u64, "kclvm_dict_values" => crate::kclvm_dict_values as *const () as u64, + "kclvm_file_read" => crate::kclvm_file_read as *const () as u64, "kclvm_iterator_cur_key" => crate::kclvm_iterator_cur_key as *const () as u64, "kclvm_iterator_cur_value" => crate::kclvm_iterator_cur_value as *const () as u64, "kclvm_iterator_delete" => crate::kclvm_iterator_delete as *const () as u64, diff --git a/kclvm/runtime/src/_kclvm_api_spec.rs b/kclvm/runtime/src/_kclvm_api_spec.rs index 9d4397eab..3fb06f91c 100644 --- a/kclvm/runtime/src/_kclvm_api_spec.rs +++ b/kclvm/runtime/src/_kclvm_api_spec.rs @@ -1,4 +1,4 @@ -//! Copyright The KCL Authors. All rights reserved. +// Copyright 2023 The KCL Authors. All rights reserved. // Auto generated by command, DONOT EDIT!!! @@ -1174,3 +1174,7 @@ // api-spec(c): kclvm_value_ref_t* kclvm_yaml_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec: kclvm_file_read +// api-spec(c): kclvm_value_ref_t* kclvm_file_read(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_file_read(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + diff --git a/kclvm/runtime/src/file/mod.rs b/kclvm/runtime/src/file/mod.rs new file mode 100644 index 000000000..bd0343e70 --- /dev/null +++ b/kclvm/runtime/src/file/mod.rs @@ -0,0 +1,24 @@ +use std::fs; + +use crate::*; + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_file_read( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(x) = args.arg_i_str(0, None) { + let contents = + fs::read_to_string(&x).expect(&format!("failed to access the file in {}", x)); + + let s = ValueRef::str(contents.as_ref()); + return s.into_raw(ctx); + } + + panic!("read() takes exactly one argument (0 given)"); +} diff --git a/kclvm/runtime/src/lib.rs b/kclvm/runtime/src/lib.rs index 80681407b..6b13596d0 100644 --- a/kclvm/runtime/src/lib.rs +++ b/kclvm/runtime/src/lib.rs @@ -104,6 +104,9 @@ pub use self::units::*; pub mod yaml; pub use self::yaml::*; +pub mod file; +pub use self::file::*; + pub mod _kcl_run; pub use self::_kcl_run::*; diff --git a/kclvm/sema/src/builtin/system_module.rs b/kclvm/sema/src/builtin/system_module.rs index cd5ca61d8..0f239ff86 100644 --- a/kclvm/sema/src/builtin/system_module.rs +++ b/kclvm/sema/src/builtin/system_module.rs @@ -1549,8 +1549,40 @@ register_collection_member! { ) } +// ------------------------------ +// file system package +// ------------------------------ + +pub const FILE: &str = "file"; +pub const FILE_FUNCTION_NAMES: &[&str] = &["read"]; +macro_rules! register_file_member { + ($($name:ident => $ty:expr)*) => ( + pub const FILE_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_file_member! { + read => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "filepath".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Read the file content from path"#, + false, + None, + ) +} + pub const STANDARD_SYSTEM_MODULES: &[&str] = &[ - COLLECTION, NET, MANIFESTS, MATH, DATETIME, REGEX, YAML, JSON, CRYPTO, BASE64, UNITS, + COLLECTION, NET, MANIFESTS, MATH, DATETIME, REGEX, YAML, JSON, CRYPTO, BASE64, UNITS, FILE, ]; pub const STANDARD_SYSTEM_MODULE_NAMES_WITH_AT: &[&str] = &[ @@ -1565,6 +1597,7 @@ pub const STANDARD_SYSTEM_MODULE_NAMES_WITH_AT: &[&str] = &[ "@crypto", "@base64", "@units", + "@file", ]; /// Get the system module members @@ -1585,6 +1618,7 @@ pub fn get_system_module_members(name: &str) -> Vec<&str> { members } COLLECTION => COLLECTION_FUNCTION_NAMES.to_vec(), + FILE => FILE_FUNCTION_NAMES.to_vec(), _ => bug!("invalid system module name '{}'", name), } } diff --git a/kclvm/tools/src/LSP/src/completion.rs b/kclvm/tools/src/LSP/src/completion.rs index b3ecf7dca..3ee8dfb2b 100644 --- a/kclvm/tools/src/LSP/src/completion.rs +++ b/kclvm/tools/src/LSP/src/completion.rs @@ -1092,6 +1092,7 @@ mod tests { "crypto", "base64", "units", + "file", ] .iter() .map(|name| KCLCompletionItem { diff --git a/test/grammar/builtins/file/load_json/main.k b/test/grammar/builtins/file/load_json/main.k new file mode 100644 index 000000000..1bda19025 --- /dev/null +++ b/test/grammar/builtins/file/load_json/main.k @@ -0,0 +1,8 @@ +import json +import file + +data_string = json.decode(file.read("test.json")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/load_json/stdout.golden b/test/grammar/builtins/file/load_json/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/load_json/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/load_json/test.json b/test/grammar/builtins/file/load_json/test.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/load_json/test.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/main.k b/test/grammar/builtins/file/load_txt/main.k new file mode 100644 index 000000000..741febc4f --- /dev/null +++ b/test/grammar/builtins/file/load_txt/main.k @@ -0,0 +1,3 @@ +import file + +a = file.read("test.txt") \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/stdout.golden b/test/grammar/builtins/file/load_txt/stdout.golden new file mode 100644 index 000000000..623ab06c1 --- /dev/null +++ b/test/grammar/builtins/file/load_txt/stdout.golden @@ -0,0 +1 @@ +a: Helloworld \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/test.txt b/test/grammar/builtins/file/load_txt/test.txt new file mode 100644 index 000000000..0cf453276 --- /dev/null +++ b/test/grammar/builtins/file/load_txt/test.txt @@ -0,0 +1 @@ +Helloworld \ No newline at end of file diff --git a/test/grammar/builtins/file/load_yaml/main.k b/test/grammar/builtins/file/load_yaml/main.k new file mode 100644 index 000000000..01a780149 --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/main.k @@ -0,0 +1,8 @@ +import yaml +import file + +data_string = yaml.decode(file.read("test.yaml")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/load_yaml/stdout.golden b/test/grammar/builtins/file/load_yaml/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/load_yaml/test.yaml b/test/grammar/builtins/file/load_yaml/test.yaml new file mode 100644 index 000000000..0ffe95c1b --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/test.yaml @@ -0,0 +1,3 @@ +key1: "value1" +key2: "value2" +data: [1, 2, 3]