diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index 3c87571ea..c3464c392 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -2020,6 +2020,7 @@ dependencies = [ "unic-ucd-category", "unicode-casing", "uuid", + "walkdir", ] [[package]] @@ -2227,9 +2228,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lsp-server" diff --git a/kclvm/makefile b/kclvm/makefile index 61c4b9074..9e119a7ee 100644 --- a/kclvm/makefile +++ b/kclvm/makefile @@ -12,18 +12,18 @@ gen-runtime-api: make -C ./runtime gen-api-spec make fmt -# Install the wasm target +# Install the wasm32-unknown-unknown target install-rustc-wasm: rustup target add wasm32-unknown-unknown +# Install the wasm-wasi target +install-rustc-wasm-wasi: + rustup target add wasm32-wasi + # Install python3 pytest install-pytest: python3 -mpip install --user -U pytest pytest-html pytest-xdist -# Install kclvm-py -install-kclvm-py: - python3 -mpip install --user -U kclvm - # ------------------------ # Compile and run # ------------------------ @@ -82,19 +82,19 @@ codecov-lcov: cargo llvm-cov --features llvm --lcov --output-path $(PWD)/.kclvm_cov/lcov.info -r --workspace --ignore-filename-regex gpyrpc.rs -- --nocapture # Test runtime libaries using python functions -test-runtime: install-kclvm-py install-pytest +test-runtime: install-pytest cd ./tests/test_units && PYTHONPATH=./../../tests/test_units/runtime python3 -m pytest -vv || { echo 'kclvm/tests/test_units failed' ; exit 1; } # E2E grammar tests. -test-grammar: install-kclvm-py install-pytest +test-grammar: install-pytest cd tests/integration/grammar && python3 -m pytest -v -n 5 # E2E grammar tests with the fast evaluator -test-grammar-evaluator: install-kclvm-py install-pytest +test-grammar-evaluator: install-pytest cd tests/integration/grammar && KCL_FAST_EVAL=1 python3 -m pytest -v -n 5 # E2E konfig tests. -test-konfig: install-kclvm-py install-pytest +test-konfig: install-pytest cd tests/integration/konfig && python3 -m pytest -v -n 5 # Parser fuzz. diff --git a/kclvm/runtime/Cargo.toml b/kclvm/runtime/Cargo.toml index ec7347c05..0532763ed 100644 --- a/kclvm/runtime/Cargo.toml +++ b/kclvm/runtime/Cargo.toml @@ -30,3 +30,6 @@ num-integer = "0.1.44" glob = "0.3.0" uuid = { version = "1.7.0", features = ["serde", "v4"] } handlebars = "5.1.2" + +[build-dependencies] +walkdir = "2.5.0" diff --git a/kclvm/runtime/Makefile b/kclvm/runtime/Makefile index 412cc61d2..4aa972968 100644 --- a/kclvm/runtime/Makefile +++ b/kclvm/runtime/Makefile @@ -1,17 +1,16 @@ default: make gen-api-spec - cargo test gen-api-spec: mkdir -p target cargo clean -q - KCLVM_RUNTIME_GEN_API_SPEC= cargo build > ./src/_kclvm_api_spec.rs.tmp + KCLVM_RUNTIME_GEN_API_SPEC= cargo build -r > ./src/_kclvm_api_spec.rs.tmp echo "// Copyright The KCL Authors. All rights reserved.\n" > ./src/_kclvm_api_spec.rs echo "// Auto generated by command, DONOT EDIT!!!\n" >> ./src/_kclvm_api_spec.rs cat ./src/_kclvm_api_spec.rs.tmp >> ./src/_kclvm_api_spec.rs rm ./src/_kclvm_api_spec.rs.tmp - make -C ./tools/kclvm-runtime-gen-api + cargo build -r diff --git a/kclvm/runtime/build.rs b/kclvm/runtime/build.rs new file mode 100644 index 000000000..390bbe3a5 --- /dev/null +++ b/kclvm/runtime/build.rs @@ -0,0 +1,302 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fs; +use std::process; +use std::process::Command; +use std::process::ExitStatus; +use walkdir::WalkDir; + +const ROOT: &str = "./src"; +const C_API_FILE: &str = "./src/_kclvm.h"; +const LL_API_FILE: &str = "./src/_kclvm.ll"; +const RUST_API_ENUM: &str = "./src/_kclvm.rs"; +const RUST_API_ADDR: &str = "./src/_kclvm_addr.rs"; + +#[derive(Debug, Default)] +struct ApiSpec { + file: String, + line: usize, + name: String, + spec_c: String, + spec_ll: String, + is_type: bool, +} + +fn main() -> Result<(), Box> { + std::env::set_var("KCLVM_RUNTIME_GEN_API_SPEC", "1"); + let specs = load_all_api_spec(ROOT); + let src = gen_c_api(&specs); + fs::write(C_API_FILE, src).unwrap_or_else(|err| { + eprintln!("Failed to write C API file: {}", err); + process::exit(1); + }); + + let src = gen_ll_api(&specs); + fs::write(LL_API_FILE, src).unwrap_or_else(|err| { + eprintln!("Failed to write LLVM API file: {}", err); + process::exit(1); + }); + + let src = gen_rust_api_enum(&specs); + fs::write(RUST_API_ENUM, src).unwrap_or_else(|err| { + eprintln!("Failed to write Rust API Enum file: {}", err); + process::exit(1); + }); + + let src = gen_rust_api_addr(&specs); + fs::write(RUST_API_ADDR, src).unwrap_or_else(|err| { + eprintln!("Failed to write Rust API Addr file: {}", err); + process::exit(1); + }); + + run_llvm_as(LL_API_FILE)?; + run_cargo_fmt()?; + Ok(()) +} + +fn load_all_api_spec(root: &str) -> Vec { + let mut specs: HashMap = HashMap::new(); + let api_spec_prefix_name = "// api-spec:"; + let api_spec_prefix_c = "// api-spec(c):"; + let api_spec_prefix_ll = "// api-spec(llvm):"; + + for entry in WalkDir::new(root).into_iter().filter_map(|e| e.ok()) { + let path = entry.path(); + if path.is_dir() || !path.to_str().unwrap().ends_with(".rs") { + continue; + } + let data = fs::read_to_string(&path).unwrap(); + let mut spec = ApiSpec::default(); + + for (i, line) in data.lines().enumerate() { + let line = line.trim(); + + if line.starts_with(api_spec_prefix_name) { + spec.file = path.display().to_string(); + spec.line = i + 1; + spec.name = line + .trim_start_matches(api_spec_prefix_name) + .trim() + .to_string(); + spec.is_type = spec.name.ends_with("_t"); + } else if line.starts_with(api_spec_prefix_c) { + if !spec.spec_c.is_empty() { + spec.spec_c.push(' '); + } + spec.spec_c + .push_str(line.trim_start_matches(api_spec_prefix_c).trim()); + } else if line.starts_with(api_spec_prefix_ll) { + if !spec.spec_ll.is_empty() { + spec.spec_ll.push(' '); + } + spec.spec_ll + .push_str(line.trim_start_matches(api_spec_prefix_ll).trim()); + } else { + if !spec.name.is_empty() { + if let Some(existing) = specs.get(&spec.name) { + eprintln!( + "WARN: {}:{} {} api-spec exists ({}:{})", + path.display(), + i + 1, + spec.name, + existing.file, + existing.line + ); + } + specs.insert(spec.name.clone(), spec); + } + spec = ApiSpec::default(); + } + } + } + + let mut spec_list: Vec = specs.into_values().collect(); + spec_list.sort_by(|a, b| a.name.cmp(&b.name)); + spec_list +} + +fn gen_c_api(specs: &[ApiSpec]) -> String { + let mut buf = String::new(); + + buf.push_str("// Copyright The KCL Authors. All rights reserved.\n\n"); + buf.push_str("// Auto generated, DONOT EDIT!!!\n\n"); + buf.push_str("#pragma once\n\n"); + buf.push_str("#ifndef _kclvm_h_\n#define _kclvm_h_\n\n"); + buf.push_str("#include \n#include \n#include \n\n"); + buf.push_str("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); + + buf.push_str("// please keep same as 'kclvm/runtime/src/kind/mod.rs#Kind'\n\n"); + buf.push_str("enum kclvm_kind_t {\n"); + buf.push_str(" Invalid = 0,\n"); + buf.push_str(" Undefined = 1,\n"); + buf.push_str(" None = 2,\n"); + buf.push_str(" Bool = 3,\n"); + buf.push_str(" Int = 4,\n"); + buf.push_str(" Float = 5,\n"); + buf.push_str(" Str = 6,\n"); + buf.push_str(" List = 7,\n"); + buf.push_str(" Dict = 8,\n"); + buf.push_str(" Schema = 9,\n"); + buf.push_str(" Error = 10,\n"); + buf.push_str(" Any = 11,\n"); + buf.push_str(" Union = 12,\n"); + buf.push_str(" BoolLit = 13,\n"); + buf.push_str(" IntLit = 14,\n"); + buf.push_str(" FloatLit = 15,\n"); + buf.push_str(" StrLit = 16,\n"); + buf.push_str(" Func = 17,\n"); + buf.push_str(" Max = 18,\n"); + buf.push_str("};\n\n"); + + for spec in specs { + if spec.is_type { + buf.push_str(&spec.spec_c); + buf.push_str("\n\n"); + } + } + + for spec in specs { + if !spec.is_type { + buf.push_str(&spec.spec_c); + buf.push_str("\n\n"); + } + } + + buf.push_str("#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n"); + buf.push_str("#endif // _kclvm_h_\n"); + + fmt_code(&buf) +} + +fn gen_ll_api(specs: &[ApiSpec]) -> String { + let mut buf = String::new(); + + buf.push_str("; Copyright The KCL Authors. All rights reserved.\n\n"); + buf.push_str("; Auto generated, DONOT EDIT!!!\n\n"); + + for spec in specs { + if spec.is_type { + buf.push_str(&spec.spec_ll); + buf.push_str("\n\n"); + } + } + + for spec in specs { + if !spec.is_type { + buf.push_str(&spec.spec_ll); + buf.push_str("\n\n"); + } + } + + buf.push_str( + "define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* %_b) {\n", + ); + buf.push_str(" call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b)\n"); + buf.push_str(" ret void\n"); + buf.push_str("}\n"); + + fmt_code(&buf) +} + +fn gen_rust_api_enum(specs: &[ApiSpec]) -> String { + let mut buf = String::new(); + + buf.push_str("// Copyright The KCL Authors. All rights reserved.\n\n"); + buf.push_str("// Auto generated, DONOT EDIT!!!\n\n"); + + // Enum ApiType + buf.push_str("#[allow(dead_code, non_camel_case_types)]\n"); + buf.push_str("#[derive(Clone, PartialEq, Eq, Debug, Hash)]\n"); + buf.push_str("pub enum ApiType {\n"); + buf.push_str(" Value,\n"); + buf.push_str("}\n"); + buf.push('\n'); + buf.push_str("impl std::fmt::Display for ApiType {\n"); + buf.push_str(" fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n"); + buf.push_str(" match self {\n"); + buf.push_str(" ApiType::Value => write!(f, \"{:?}\", \"api::kclvm::Value\"),\n"); + buf.push_str(" }\n"); + buf.push_str(" }\n"); + buf.push_str("}\n"); + buf.push('\n'); + buf.push_str("impl ApiType {\n"); + buf.push_str(" #[allow(dead_code)]\n"); + buf.push_str(" pub fn name(&self) -> String {\n"); + buf.push_str(" format!(\"{self:?}\")\n"); + buf.push_str(" }\n"); + buf.push_str("}\n"); + buf.push('\n'); + // Enum ApiFunc + buf.push_str("#[allow(dead_code, non_camel_case_types)]\n"); + buf.push_str("#[derive(Clone, PartialEq, Eq, Debug, Hash)]\n"); + buf.push_str("pub enum ApiFunc {\n"); + + for spec in specs { + if !spec.is_type { + buf.push_str(" "); + buf.push_str(&spec.name); + buf.push_str(",\n"); + } + } + + buf.push_str("}\n"); + buf.push('\n'); + buf.push_str("impl std::fmt::Display for ApiFunc {\n"); + buf.push_str(" fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n"); + buf.push_str(" write!(f, \"{self:?}\")\n"); + buf.push_str(" }\n"); + buf.push_str("}\n"); + buf.push('\n'); + buf.push_str("impl ApiFunc {\n"); + buf.push_str(" #[allow(dead_code)]\n"); + buf.push_str(" pub fn name(&self) -> String {\n"); + buf.push_str(" format!(\"{self:?}\")\n"); + buf.push_str(" }\n"); + buf.push_str("}\n"); + + fmt_code(&buf) +} + +fn gen_rust_api_addr(specs: &[ApiSpec]) -> String { + let mut buf = String::new(); + + buf.push_str("// Copyright The KCL Authors. All rights reserved.\n\n"); + buf.push_str("// Auto generated, DONOT EDIT!!!\n\n"); + + buf.push_str("#[allow(dead_code)]\n"); + buf.push_str("pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 {\n"); + buf.push_str(" match name {\n"); + + for spec in specs { + if !spec.is_type { + buf.push_str(" \""); + buf.push_str(&spec.name); + buf.push_str("\" => crate::"); + buf.push_str(&spec.name); + buf.push_str(" as *const () as u64,\n"); + } + } + + buf.push_str(" _ => panic!(\"unknown {name}\"),\n"); + buf.push_str(" }\n"); + buf.push_str("}\n"); + + fmt_code(&buf) +} + +fn fmt_code(s: &str) -> String { + s.split("\n\n\n") + .collect::>() + .join("\n\n") + .trim() + .to_string() + + "\n" +} + +fn run_llvm_as(file_path: &str) -> Result { + Command::new("llvm-as").arg(file_path).status() +} + +fn run_cargo_fmt() -> Result { + Command::new("cargo").arg("fmt").status() +} diff --git a/kclvm/runtime/readme.md b/kclvm/runtime/readme.md deleted file mode 100644 index 1ff43103d..000000000 --- a/kclvm/runtime/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# KCLVM - runtime - -KCLVM runtime library. - -- run test: `make` -- regenerate llvm-ir file: `make gen-api-spec` -- lint code: `cargo clippy` diff --git a/kclvm/runtime/src/_kclvm.bc b/kclvm/runtime/src/_kclvm.bc index a9ffd1ab7..2fc81056d 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 a981f2404..e5baa4b5d 100644 --- a/kclvm/runtime/src/_kclvm.h +++ b/kclvm/runtime/src/_kclvm.h @@ -19,38 +19,23 @@ extern "C" { enum kclvm_kind_t { Invalid = 0, - - // only for value - - Undefined = 1, + Undefined = 1, None = 2, - - // for value & type - Bool = 3, Int = 4, Float = 5, Str = 6, List = 7, Dict = 8, - Schema = 9, Error = 10, - - // only for type - Any = 11, Union = 12, - BoolLit = 13, IntLit = 14, FloatLit = 15, StrLit = 16, - Func = 17, - - // max num - Max = 18, }; diff --git a/kclvm/runtime/src/_kclvm.ll b/kclvm/runtime/src/_kclvm.ll index a60a69659..448df7a86 100644 --- a/kclvm/runtime/src/_kclvm.ll +++ b/kclvm/runtime/src/_kclvm.ll @@ -663,6 +663,6 @@ declare %kclvm_value_ref_t* @kclvm_yaml_encode_all(%kclvm_context_t* %ctx, %kclv declare %kclvm_value_ref_t* @kclvm_yaml_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* %_b) { - call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b) - ret void + call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b) + ret void } diff --git a/kclvm/runtime/tools/kclvm-runtime-gen-api/Makefile b/kclvm/runtime/tools/kclvm-runtime-gen-api/Makefile deleted file mode 100644 index 9701cf5c0..000000000 --- a/kclvm/runtime/tools/kclvm-runtime-gen-api/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -default: - go run main.go \ - -root=../../src \ - -c-api=../../src/_kclvm.h \ - -ll-api=../../src/_kclvm.ll \ - -rust-api-enum=../../src/_kclvm.rs \ - -rust-api-addr=../../src/_kclvm_addr.rs - - llvm-as ../../src/_kclvm.ll diff --git a/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go b/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go deleted file mode 100644 index fdc4ad5fe..000000000 --- a/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright The KCL Authors. All rights reserved. - -package main - -import ( - "bytes" - "flag" - "fmt" - "os" - "path/filepath" - "regexp" - "sort" - "strings" - "text/template" -) - -var ( - flagRoot = flag.String("root", ".", "set kclvm-runtime root") - flagGenCApi = flag.String("c-api", "", "set c header file") - flagGenLLApi = flag.String("ll-api", "", "set llvm-ll file") - flagGenRustApiEnum = flag.String("rust-api-enum", "", "set rust-api-enum file") - flagGenRustApiAddr = flag.String("rust-api-addr", "", "set rust-api-addr file") -) - -func main() { - flag.Parse() - - specList := LoadAllApiSpec(*flagRoot) - if filename := *flagGenCApi; filename != "" { - src := genCApi(specList) - if err := os.WriteFile(filename, []byte(src), 0666); err != nil { - panic(err) - } - } - if filename := *flagGenLLApi; filename != "" { - src := genLLApi(specList) - if err := os.WriteFile(filename, []byte(src), 0666); err != nil { - panic(err) - } - } - if filename := *flagGenRustApiEnum; filename != "" { - src := genRustApiEnum(specList) - if err := os.WriteFile(filename, []byte(src), 0666); err != nil { - panic(err) - } - } - if filename := *flagGenRustApiAddr; filename != "" { - src := genRustApiAddr(specList) - if err := os.WriteFile(filename, []byte(src), 0666); err != nil { - panic(err) - } - } -} - -func genCApi(specs []ApiSpec) string { - tmpl, err := template.New("c-api").Parse(tmplCApi) - if err != nil { - panic(err) - } - - var buf bytes.Buffer - err = tmpl.Execute(&buf, specs) - if err != nil { - panic(err) - } - return fmtCode(buf.String()) -} - -func genLLApi(specs []ApiSpec) string { - tmpl, err := template.New("ll-api").Parse(tmplLLApi) - if err != nil { - panic(err) - } - - var buf bytes.Buffer - err = tmpl.Execute(&buf, specs) - if err != nil { - panic(err) - } - return fmtCode(buf.String()) -} - -func genRustApiEnum(specs []ApiSpec) string { - tmpl, err := template.New("rust-api-enum").Parse(tmplRustEnum) - if err != nil { - panic(err) - } - - var buf bytes.Buffer - err = tmpl.Execute(&buf, specs) - if err != nil { - panic(err) - } - return fmtCode(buf.String()) -} - -func genRustApiAddr(specs []ApiSpec) string { - tmpl, err := template.New("rust-api-addr").Parse(tmplRustAddr) - if err != nil { - panic(err) - } - - var buf bytes.Buffer - err = tmpl.Execute(&buf, specs) - if err != nil { - panic(err) - } - return fmtCode(buf.String()) -} - -func fmtCode(s string) string { - for { - if !strings.Contains(s, "\n\n\n") { - s = strings.TrimSpace(s) + "\n" - return s - } - s = strings.ReplaceAll(s, "\n\n\n", "\n\n") - } -} - -// ---------------------------------------------------------------------------- - -const ( - apiSpecPrefix_Name = "// api-spec:" - apiSpecPrefix_CApi = "// api-spec(c):" - apiSpecPrefix_LLApi = "// api-spec(llvm):" -) - -type ApiSpec struct { - File string - Line int - Name string // api-spec: kclvm_context_new - SpecC string // api-spec(c): i32 kclvm_context_new(); - SpecLL string // api-spec(llvm): declare i32* @kclvm_context_new() - IsType bool -} - -func LoadAllApiSpec(root string) []ApiSpec { - m := make(map[string]ApiSpec) - filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if err != nil { - panic(err) - } - if info.IsDir() { - return nil - } - - if !strings.HasSuffix(path, ".rs") { - return nil - } - - data, err := os.ReadFile(path) - if err != nil { - panic(err) - } - - var spec ApiSpec - for i, line := range strings.Split(string(data), "\n") { - line := strings.TrimSpace(line) - switch { - case strings.HasPrefix(line, apiSpecPrefix_Name): - spec.File = path - spec.Line = i + 1 - spec.Name = strings.TrimSpace(strings.TrimPrefix(line, apiSpecPrefix_Name)) - spec.IsType = strings.HasSuffix(spec.Name, "_t") - case strings.HasPrefix(line, apiSpecPrefix_CApi): - if spec.SpecC != "" { - spec.SpecC += " " - } - spec.SpecC += strings.TrimSpace(strings.TrimPrefix(line, apiSpecPrefix_CApi)) - case strings.HasPrefix(line, apiSpecPrefix_LLApi): - if spec.SpecLL != "" { - spec.SpecLL += " " - } - spec.SpecLL += strings.TrimSpace(strings.TrimPrefix(line, apiSpecPrefix_LLApi)) - default: - if matched, _ := regexp.MatchString(`//\s*api-spec`, line); matched { - panic(fmt.Errorf("%s:%d invalid 'api-spec'", path, i+1)) - } - if spec.Name != "" { - if x, ok := m[spec.Name]; ok { - fmt.Printf("WARN: %s:%d %s api-spec exits (%s:%d)\n", path, i+1, spec.Name, x.File, x.Line) - } - m[spec.Name] = spec - } - spec = ApiSpec{} - } - } - - return nil - }) - - var specs []ApiSpec - for _, x := range m { - specs = append(specs, x) - } - sort.Slice(specs, func(i, j int) bool { - return specs[i].Name < specs[j].Name - }) - return specs -} - -// ---------------------------------------------------------------------------- - -const tmplCApi = ` -{{$specList := .}} - -// Copyright The KCL Authors. All rights reserved. - -// Auto generated, DONOT EDIT!!! - -#pragma once - -#ifndef _kclvm_h_ -#define _kclvm_h_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// please keep same as 'kclvm/runtime/src/kind/mod.rs#Kind' - -enum kclvm_kind_t { - Invalid = 0, - - // only for value - - Undefined = 1, - None = 2, - - // for value & type - - Bool = 3, - Int = 4, - Float = 5, - Str = 6, - List = 7, - Dict = 8, - - Schema = 9, - Error = 10, - - // only for type - - Any = 11, - Union = 12, - - BoolLit = 13, - IntLit = 14, - FloatLit = 15, - StrLit = 16, - - Func = 17, - - // max num - - Max = 18, -}; - -{{range $_, $spec := $specList}} -{{if ($spec.IsType)}}{{$spec.SpecC}}{{end}} -{{end}} - -{{range $_, $spec := $specList}} -{{if (not $spec.IsType)}}{{$spec.SpecC}}{{end}} -{{end}} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _kclvm_h_ -` - -// ---------------------------------------------------------------------------- - -const tmplLLApi = ` -{{$specList := .}} - -; Copyright The KCL Authors. All rights reserved. - -; Auto generated, DONOT EDIT!!! - -{{range $_, $spec := $specList}} -{{if ($spec.IsType)}}{{$spec.SpecLL}}{{end}} -{{end}} - -{{range $_, $spec := $specList}} -{{if (not $spec.IsType)}}{{$spec.SpecLL}}{{end}} -{{end}} - -define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* %_b) { - call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b) - ret void -} -` - -// ---------------------------------------------------------------------------- - -const tmplRustEnum = ` -{{$specList := .}} - -// Copyright The KCL Authors. All rights reserved. - -// Auto generated, DONOT EDIT!!! - -#[allow(dead_code, non_camel_case_types)] -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum ApiType { - Value, -} - -impl std::fmt::Display for ApiType { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - ApiType::Value => write!(f, "{:?}", "api::kclvm::Value"), - } - } -} - -impl ApiType { - #[allow(dead_code)] - pub fn name(&self) -> String { - format!("{self:?}") - } -} - -#[allow(dead_code, non_camel_case_types)] -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum ApiFunc { - {{range $_, $spec := $specList}}{{if (not $spec.IsType)}} - {{- $spec.Name}}, - {{end}}{{end}} -} - -impl std::fmt::Display for ApiFunc { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{self:?}") - } -} - -impl ApiFunc { - #[allow(dead_code)] - pub fn name(&self) -> String { - format!("{self:?}") - } -} -` - -// ---------------------------------------------------------------------------- - -const tmplRustAddr = ` -{{$specList := .}} - -// Copyright The KCL Authors. All rights reserved. - -// Auto generated, DONOT EDIT!!! - -#[allow(dead_code)] -pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { - match name { - {{- range $_, $spec := $specList -}}{{if (not $spec.IsType)}} - "{{$spec.Name}}" => crate::{{$spec.Name}} as *const () as u64, - {{- end}}{{end}} - _ => panic!("unknown {name}"), - } -} -` - -// ---------------------------------------------------------------------------- diff --git a/test/grammar/syntax/else_if_token/stderr.golden b/test/grammar/syntax/else_if_token/stderr.golden new file mode 100644 index 000000000..6a69a43f5 --- /dev/null +++ b/test/grammar/syntax/else_if_token/stderr.golden @@ -0,0 +1,62 @@ +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:3:1 + | +3 | else if False: + | 'else if' here is invalid in KCL, consider using the 'elif' keyword + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:3:9 + | +3 | else if False: + | ^ expected one of [":"] got identifier + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:3:14 + | +3 | else if False: + | ^ expected one of ["identifier", "literal", "(", "[", "{"] got : + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:3:14 + | +3 | else if False: + | ^ expected one of ["any", "bool", "int", "float", "str", "True", "False", "identifier", "literal", "[", "{", ")"] got newline + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:4:5 + | +4 | b = 1 + | ^ expected one of ["="] got indent + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:4:5 + | +4 | b = 1 + | ^ expected one of ["identifier"] got indent + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:4:5 + | +4 | b = 1 + | ^ unexpected token 'indent' + | + +error[E1001]: InvalidSyntax + --> ${CWD}/main.k:4:9 + | +4 | b = 1 + | ^ unexpected token 'dedent' + | + +error[E2L23]: CompileError + --> ${CWD}/main.k:3:14 + | +3 | else if False: + | ^ missing target in the assign statement + | diff --git a/test/grammar/syntax/else_if_token/stderr.golden.py b/test/grammar/syntax/else_if_token/stderr.golden.py deleted file mode 100644 index 902f563d4..000000000 --- a/test/grammar/syntax/else_if_token/stderr.golden.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys -import kclvm.kcl.error as kcl_error -import os - -cwd = os.path.dirname(os.path.realpath(__file__)) - -kcl_error.print_kcl_error_message( - kcl_error.get_exception( - err_type=kcl_error.ErrType.CompileError_TYPE, - file_msgs=[ - kcl_error.ErrFileMsg( - filename=cwd + "/main.k", - line_no=3, - col_no=6, - ) - ], - arg_msg="'else if' here is invalid in KCL, consider using the 'elif' keyword", - file=sys.stdout, - ) -)