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

[v0.9.0-alpha.1] feat: top level variable back reference #1104

Merged
merged 3 commits into from
May 8, 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
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.7
0.9.0-alpha.1
9 changes: 5 additions & 4 deletions kclvm/compiler/src/codegen/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
use std::error;
use std::fmt::{self, Debug};

pub const VALUE_TYPE_NOT_FOUND_MSG: &str = "Type is not found";
pub const CONTEXT_VAR_NOT_FOUND_MSG: &str = "Context variable is not found";
pub const FUNCTION_RETURN_VALUE_NOT_FOUND_MSG: &str = "Function return value is not found";
pub const COMPILE_ERROR_MSG: &str = "Compile error";
pub const VALUE_TYPE_NOT_FOUND_MSG: &str = "Internal error, value type is not found";
pub const CONTEXT_VAR_NOT_FOUND_MSG: &str = "Internal error, context variable is not found";
pub const INTERNAL_ERROR_MSG: &str = "Internal error, please report a bug to us";
pub const FUNCTION_RETURN_VALUE_NOT_FOUND_MSG: &str =
"Internal error, function return value is not found";
pub const COMPILE_ERROR_MSG: &str = "Compile error";
pub const CODE_GEN_ERROR_MSG: &str = "Code gen error";
pub const INVALID_OPERATOR_MSG: &str = "Invalid operator";
pub const INVALID_JOINED_STR_MSG: &str = "Invalid AST JoinedString value";
Expand Down
66 changes: 63 additions & 3 deletions kclvm/compiler/src/codegen/llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1311,8 +1311,10 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let tpe = self.value_ptr_type().into_pointer_type();
let void_type = self.context.void_type();
let context_ptr_type = self.context_ptr_type();
let fn_type = tpe.fn_type(&[context_ptr_type.into()], false);
let void_fn_type = void_type.fn_type(&[context_ptr_type.into()], false);
let scope_ptr_type = self.scope_ptr_type();
let fn_type = tpe.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false);
let void_fn_type =
void_type.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false);
let has_main_pkg = self.program.pkgs.contains_key(MAIN_PKG_PATH);
let function = if self.no_link {
let mut modules = self.modules.borrow_mut();
Expand Down Expand Up @@ -1756,6 +1758,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let variables = last.variables.borrow();
if let Some(var) = variables.get(&name.to_string()) {
self.builder.build_store(*var, value);
if save_scope {
self.build_void_call(
&ApiFunc::kclvm_scope_set.name(),
&[
self.current_runtime_ctx_ptr(),
self.current_scope_ptr(),
self.native_global_string(&current_pkgpath, "").into(),
self.native_global_string(name, "").into(),
value,
],
);
}
existed = true;
}
}
Expand All @@ -1766,6 +1780,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let var_name = format!("${}.${}", pkgpath_without_prefix!(pkgpath), name);
let pointer = self.new_global_kcl_value_ptr(&var_name);
self.builder.build_store(pointer, value);
if save_scope {
self.build_void_call(
&ApiFunc::kclvm_scope_set.name(),
&[
self.current_runtime_ctx_ptr(),
self.current_scope_ptr(),
self.native_global_string(&current_pkgpath, "").into(),
self.native_global_string(name, "").into(),
value,
],
);
}
if !variables.contains_key(name) {
variables.insert(name.to_string(), pointer);
}
Expand Down Expand Up @@ -1993,7 +2019,41 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
}
}
} else {
self.builder.build_load(*var, name)
// Not a local schema attribute or a global type.
let key = format!("{}.{name}", pkgpath_without_prefix!(pkgpath));
let is_in_lambda = self.is_in_lambda();
if !is_in_schema
&& !is_in_lambda
&& index <= GLOBAL_LEVEL
&& !self.local_vars.borrow().contains(name)
&& self.setter_keys.borrow().contains(&key)
{
let target = self
.target_vars
.borrow_mut()
.last()
.expect(kcl_error::INTERNAL_ERROR_MSG)
.clone();
self.build_call(
&ApiFunc::kclvm_scope_get.name(),
&[
// Runtime context ptr
self.current_runtime_ctx_ptr(),
// Scope ptr
self.current_scope_ptr(),
// Package path
self.native_global_string(&pkgpath, "").into(),
// Attribute name
self.native_global_string(name, "").into(),
// Target
self.native_global_string(&target, "").into(),
// Default
self.builder.build_load(*var, name),
],
)
} else {
self.builder.build_load(*var, name)
}
};
result = Ok(value);
break;
Expand Down
4 changes: 2 additions & 2 deletions kclvm/compiler/src/codegen/llvm/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
};
}
// Pre define global variables with setter functions.
// self.predefine_global_setters(module);
self.predefine_global_setters(module);
}

pub fn predefine_global_types(&self, name: &str) {
Expand All @@ -59,7 +59,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {

/// Predefine all global variables.
pub fn predefine_global_setters(&self, module: &'ctx ast::Module) {
// New a function block to the global setter constrcution process.
// New a function block to the global setter construction process.
let global_setter_block = self.append_block("");
self.br(global_setter_block);
self.builder.position_at_end(global_setter_block);
Expand Down
14 changes: 11 additions & 3 deletions kclvm/compiler/src/codegen/llvm/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> {
PKG_INIT_FUNCTION_SUFFIX
);
let tpe = self.context.void_type();
let fn_type = tpe.fn_type(&[self.context_ptr_type().into()], false);
let fn_type = tpe.fn_type(
&[self.context_ptr_type().into(), self.scope_ptr_type().into()],
false,
);
let function = module.add_function(
// Function name
&module_name,
Expand Down Expand Up @@ -367,10 +370,14 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> {
);
}
let tpe = self.context.void_type();
let fn_type = tpe.fn_type(&[self.context_ptr_type().into()], false);
let fn_type = tpe.fn_type(
&[self.context_ptr_type().into(), self.scope_ptr_type().into()],
false,
);
module.add_function(&name, fn_type, Some(Linkage::External))
};
let ctx = self.current_runtime_ctx_ptr();
let scope = self.current_scope_ptr();
let pkgpath_value = self.native_global_string_value(&name);
let is_imported = self
.build_call(
Expand All @@ -389,7 +396,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> {
self.builder
.build_conditional_branch(is_not_imported, then_block, else_block);
self.builder.position_at_end(then_block);
self.builder.build_call(function, &[ctx.into()], "");
self.builder
.build_call(function, &[ctx.into(), scope.into()], "");
self.br(else_block);
self.builder.position_at_end(else_block);
}
Expand Down
8 changes: 7 additions & 1 deletion kclvm/error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,13 @@ impl SessionDiagnostic for Diagnostic {
match Session::new_with_file_and_code(&msg.range.0.filename, None) {
Ok(sess) => {
let source = sess.sm.lookup_source_file(new_byte_pos(0));
let line = source.get_line((msg.range.0.line - 1) as usize);
let line = source.get_line(
(if msg.range.0.line >= 1 {
msg.range.0.line - 1
} else {
0
}) as usize,
);
match line.as_ref() {
Some(content) => {
let length = content.chars().count();
Expand Down
15 changes: 10 additions & 5 deletions kclvm/runtime/src/_kcl_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub unsafe extern "C" fn _kcl_run(
) -> kclvm_size_t {
// Init runtime context with options
let ctx = Box::new(new_ctx_with_opts(opts, &c2str_vec(path_selector))).into_raw();
let scope = kclvm_scope_new();
let option_keys = std::slice::from_raw_parts(option_keys, option_len as usize);
let option_values = std::slice::from_raw_parts(option_values, option_len as usize);
for i in 0..(option_len as usize) {
Expand Down Expand Up @@ -130,9 +131,7 @@ pub unsafe extern "C" fn _kcl_run(
}
})
}));
// let scope = Box::into_raw(Box::new(LazyEvalScope::default()));
// let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, scope, kclvm_main_ptr));
let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, kclvm_main_ptr));
let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, scope, kclvm_main_ptr));
std::panic::set_hook(prev_hook);
KCL_RUNTIME_PANIC_RECORD.with(|record| {
let record = record.borrow();
Expand Down Expand Up @@ -162,20 +161,26 @@ pub unsafe extern "C" fn _kcl_run(
copy_str_to(&json_panic_info, err_buffer, err_buffer_len);
// Delete the context
kclvm_context_delete(ctx);
// Delete the scope
kclvm_scope_delete(scope);
result.is_err() as kclvm_size_t
}

unsafe fn _kcl_run_in_closure(
ctx: *mut Context,
scope: *mut LazyEvalScope,
kclvm_main_ptr: u64, // main.k => kclvm_main
) {
let kclvm_main = (&kclvm_main_ptr as *const u64) as *const ()
as *const extern "C" fn(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t;
as *const extern "C" fn(
ctx: *mut kclvm_context_t,
scope: *mut kclvm_eval_scope_t,
) -> *mut kclvm_value_ref_t;

unsafe {
if kclvm_main.is_null() {
panic!("kcl program main function not found");
}
(*kclvm_main)(ctx);
(*kclvm_main)(ctx, scope);
}
}
Binary file modified kclvm/runtime/src/_kclvm.bc
Binary file not shown.
2 changes: 1 addition & 1 deletion kclvm/runtime/src/_kclvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ kclvm_value_ref_t* kclvm_schema_value_new(kclvm_context_t* ctx, kclvm_value_ref_

void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter);

void kclvm_scope_free(kclvm_eval_scope_t* scope);
void kclvm_scope_delete(kclvm_eval_scope_t* scope);

kclvm_value_ref_t* kclvm_scope_get(kclvm_context_t* ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, char* target, kclvm_value_ref_t* default);

Expand Down
2 changes: 1 addition & 1 deletion kclvm/runtime/src/_kclvm.ll
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ declare %kclvm_value_ref_t* @kclvm_schema_value_new(%kclvm_context_t* %ctx, %kcl

declare void @kclvm_scope_add_setter(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i64* %setter);

declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope);
declare void @kclvm_scope_delete(%kclvm_eval_scope_t* %scope);

declare %kclvm_value_ref_t* @kclvm_scope_get(%kclvm_context_t* %ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i8* %target, %kclvm_value_ref_t* %default);

Expand Down
2 changes: 1 addition & 1 deletion kclvm/runtime/src/_kclvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub enum ApiFunc {
kclvm_schema_value_check,
kclvm_schema_value_new,
kclvm_scope_add_setter,
kclvm_scope_free,
kclvm_scope_delete,
kclvm_scope_get,
kclvm_scope_new,
kclvm_scope_set,
Expand Down
2 changes: 1 addition & 1 deletion kclvm/runtime/src/_kclvm_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 {
"kclvm_schema_value_check" => crate::kclvm_schema_value_check as *const () as u64,
"kclvm_schema_value_new" => crate::kclvm_schema_value_new as *const () as u64,
"kclvm_scope_add_setter" => crate::kclvm_scope_add_setter as *const () as u64,
"kclvm_scope_free" => crate::kclvm_scope_free as *const () as u64,
"kclvm_scope_delete" => crate::kclvm_scope_delete as *const () as u64,
"kclvm_scope_get" => crate::kclvm_scope_get as *const () as u64,
"kclvm_scope_new" => crate::kclvm_scope_new as *const () as u64,
"kclvm_scope_set" => crate::kclvm_scope_set as *const () as u64,
Expand Down
6 changes: 3 additions & 3 deletions kclvm/runtime/src/_kclvm_api_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
// api-spec(c): kclvm_eval_scope_t* kclvm_scope_new();
// api-spec(llvm): declare %kclvm_eval_scope_t* @kclvm_scope_new();

// api-spec: kclvm_scope_free
// api-spec(c): void kclvm_scope_free(kclvm_eval_scope_t* scope);
// api-spec(llvm): declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope);
// api-spec: kclvm_scope_delete
// api-spec(c): void kclvm_scope_delete(kclvm_eval_scope_t* scope);
// api-spec(llvm): declare void @kclvm_scope_delete(%kclvm_eval_scope_t* %scope);

// api-spec: kclvm_scope_add_setter
// api-spec(c): void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter);
Expand Down
18 changes: 0 additions & 18 deletions kclvm/runtime/src/_kclvm_main_win.c

This file was deleted.

2 changes: 1 addition & 1 deletion kclvm/runtime/src/context/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub unsafe extern "C" fn kclvm_scope_new() -> *mut kclvm_eval_scope_t {

#[no_mangle]
#[runtime_fn]
pub unsafe extern "C" fn kclvm_scope_free(scope: *mut kclvm_eval_scope_t) {
pub unsafe extern "C" fn kclvm_scope_delete(scope: *mut kclvm_eval_scope_t) {
drop(Box::from_raw(scope));
}

Expand Down
15 changes: 15 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_10/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
schema Data:
name: str
version?: str

data1 = Data {
name = data2.name
}

data2 = Data {
name = "1"
version = version
}

# Global version
version = "v0.1.0"
6 changes: 6 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_10/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
data1:
name: '1'
data2:
name: '1'
version: v0.1.0
version: v0.1.0
2 changes: 2 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_7/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
b = a
a = 1
2 changes: 2 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_7/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
b: 1
a: 1
3 changes: 3 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_8/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
b = a + c
a = 1
c = a + 1
3 changes: 3 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_8/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
b: 3
a: 1
c: 2
Empty file.
3 changes: 3 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_9/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pkg

output = pkg.output
4 changes: 4 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_9/pkg/base.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
schema MyApp:
name: str
versions: {str:str}
version = versions[name]
5 changes: 5 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_9/pkg/input.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
output = MyApp{
name = name
versions = my_versions
}
name = "my_app"
3 changes: 3 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_9/pkg/versions.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
my_versions = {
"my-app": "1.0.0"
}
4 changes: 4 additions & 0 deletions test/grammar/schema/irrelevant_order/simple_9/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output:
name: my_app
versions:
my-app: 1.0.0
Loading