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

internal: KCL modules, part 1 #4149

Merged
merged 45 commits into from
Oct 17, 2024
Merged

internal: KCL modules, part 1 #4149

merged 45 commits into from
Oct 17, 2024

Conversation

jtran
Copy link
Collaborator

@jtran jtran commented Oct 13, 2024

Addresses #4080. (Not ready to close it yet.)

Important

Requires a fix for #4147 before it can work in ZMA.

Overview

// numbers.kcl
export fn inc = (x) => {
  return x + 1
}
import inc from "numbers.kcl"

answer = inc(41)

This also implements multiple imports with optional renaming.

import inc, dec from "numbers.kcl"
import identity as id, length as len from "utils.kcl"

Note: Imported files must be in the same directory.

Things for a follow-up PR:

  • [BUG]: Import does not work for any *.obj *.step #4147. Currently, we cannot read files in WebAssembly, i.e. ZMA.
  • Docs
  • Should be an error to import anywhere besides the top level. Needs parser restructuring to track the context of a "function body".
  • Should be an error to have export anywhere besides the top level. It has no effect, but we should tell people it's not valid instead of silently ignoring it.
  • Error message for cycle detection is funky because the Rust side doesn't actually know the name of the first file. Message will say "b -> a -> b" instead of "a -> b -> a" when "a" is the top-level file.
  • Cache imported files so that they don't need to be re-parsed and re-executed.

Copy link

qa-wolf bot commented Oct 13, 2024

QA Wolf here! As you write new code it's important that your test coverage is keeping up.
Click here to request test coverage for this PR!

Copy link

vercel bot commented Oct 13, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
modeling-app ✅ Ready (Inspect) Visit Preview Oct 16, 2024 10:44pm

@jtran jtran requested review from nrc and adamchalmers October 13, 2024 19:06
@jtran jtran marked this pull request as ready for review October 13, 2024 19:21
Copy link

codecov bot commented Oct 13, 2024

Codecov Report

Attention: Patch coverage is 75.84746% with 114 lines in your changes missing coverage. Please review.

Project coverage is 85.83%. Comparing base (7d44de0) to head (eddbf61).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/wasm-lib/kcl/src/ast/types.rs 22.89% 64 Missing ⚠️
src/wasm-lib/kcl/src/executor.rs 87.06% 15 Missing ⚠️
src/wasm-lib/kcl/src/parser/parser_impl.rs 91.58% 9 Missing ⚠️
src/wasm-lib/kcl-to-core/src/conn_mock_core.rs 45.45% 6 Missing ⚠️
src/wasm-lib/kcl/src/engine/conn.rs 45.45% 6 Missing ⚠️
src/wasm-lib/kcl/src/walk/ast_walk.rs 0.00% 5 Missing ⚠️
src/wasm-lib/kcl/src/fs/local.rs 50.00% 4 Missing ⚠️
src/wasm-lib/kcl/src/errors.rs 60.00% 2 Missing ⚠️
src/wasm-lib/kcl-test-server/src/lib.rs 0.00% 1 Missing ⚠️
src/wasm-lib/kcl/src/ast/modify.rs 66.66% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4149      +/-   ##
==========================================
- Coverage   85.99%   85.83%   -0.16%     
==========================================
  Files          76       76              
  Lines       26700    27155     +455     
==========================================
+ Hits        22960    23309     +349     
- Misses       3740     3846     +106     
Flag Coverage Δ
wasm-lib 85.83% <75.84%> (-0.16%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@nrc nrc added the kcl Language and compiler features label Oct 13, 2024
Copy link
Contributor

@nrc nrc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I'm pretty unfamiliar with the engine and program memory code, so I'd want to get Adam to take a look too.

src/wasm-lib/kcl/src/ast/types.rs Outdated Show resolved Hide resolved
/// this is empty, we're not currently executing a use statement.
pub import_stack: Vec<std::path::PathBuf>,
/// The directory of the current project. This is used for resolving import
/// paths.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you document when it can be None and what that means? Depending on the answer, it might be better to use a custom enum rather than Option

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume 'none' means current working directory but yeah should be documented

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an enum, so hopefully it's clearer. 282225c

Copy link
Collaborator Author

@jtran jtran Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, the ProjectDirectory enum that I made is giving me trouble with wasm. I get the error "the trait FromWasmAbi is not implemented for ProjectDirectory". wasm_bindgen doesn't support them rustwasm/wasm-bindgen#2407.

How are we able to use enums with values elsewhere, like here?

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)]
#[databake(path = kcl_lib::ast::types)]
#[ts(export)]
#[serde(tag = "type")]
pub enum BodyItem {
ExpressionStatement(ExpressionStatement),
VariableDeclaration(VariableDeclaration),
ReturnStatement(ReturnStatement),
}

I reverted back to the Option<String> and added a comment explaining None.

src/wasm-lib/kcl/src/unparser.rs Outdated Show resolved Hide resolved
@@ -178,7 +178,7 @@ async fn snapshot_endpoint(body: Bytes, state: ExecutorContext) -> Response<Body
// Let users know if the test is taking a long time.
let (done_tx, done_rx) = oneshot::channel::<()>();
let timer = time_until(done_rx);
let snapshot = match state.execute_and_prepare_snapshot(&program, id_generator).await {
let snapshot = match state.execute_and_prepare_snapshot(&program, id_generator, None).await {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you avoid modifying the execute_and_prepare_snapshot method, this PR diff will be much smaller (just make a new method that lets you take the optional param instead, and make the existing one set it to None)

src/wasm-lib/kcl/src/ast/types.rs Outdated Show resolved Hide resolved
/// this is empty, we're not currently executing a use statement.
pub import_stack: Vec<std::path::PathBuf>,
/// The directory of the current project. This is used for resolving import
/// paths.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume 'none' means current working directory but yeah should be documented

source_ranges: vec![import_stmt.into()],
}));
}
let source = self.fs.read_to_string(&resolved_path, source_range).await?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't have to be in this PR, but eventually, we'll want to cache the "read, parse, evaluate file" logic. If multiple files all import a shared library like helpers.kcl or polygon.kcl then we'll want to avoid re-parsing them.

if !module_exports.contains(&import_item.name.name) {
return Err(KclError::Semantic(KclErrorDetails {
message: format!(
"Cannot import \"{}\" from module because it is not exported. Add \"export\" before the definition to export it.",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually (doesn't have to be in this PR) it'd be good to check for export-violation before we evaluate it -- just to return errors quicker.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love if we had a simple way to extract all the exported identifiers (and their type?) without evaluating anything. But yeah, I don't think we're there yet.

src/wasm-lib/kcl/src/ast/types.rs Outdated Show resolved Hide resolved
src/wasm-lib/kcl/src/parser/parser_impl.rs Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kcl Language and compiler features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants