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

call() scope does not override imported symbols #116

Open
huafu opened this issue Oct 8, 2022 · 6 comments
Open

call() scope does not override imported symbols #116

huafu opened this issue Oct 8, 2022 · 6 comments

Comments

@huafu
Copy link

huafu commented Oct 8, 2022

I've wrote a Typescript transformer for ucode as well as typings so that one can write ucode code with strict typings. I've also wrote a test library with spies and stubs so that ucode projects can have unit tests also written in Typescript. it's going to be on my public Github once ready (or at least when in a more advanced stage).
For the spies and stubs, I'm using the call function which is pretty handy. Tho there is one blocking issue:

// my_lib.uc
import { to_stub } from './other_lib.uc';

function fn_to_test() {
  // ...
  to_stub("hello");
  // ...
}

export { fn_to_test };
// my_lib.spec.uc
call(fn_to_test, { to_stub: () => null });

here I was expecting fn_to_test to use the dummy () => null when calling to_stub instead of the one imported from my_lib.uc.
I guess it's the normal behavior, tho it'd be nice if the scope given to call() could override imported symbols as well as globals.

@jow-
Copy link
Owner

jow- commented Oct 8, 2022

Imported symbols act like local variables, that's why you can't shadow them by overriding the scope (once the compiled bytecode runs, accessing imported symbols is not a property lookup in the global scope but a direct stack slot / upvalue access, basically the same as a local variable).

Without introducing a set of debug/introspection APIs, the only solution I can think of is compiling and loading the code to test at runtime using loadfile() / loadstring() and modifying module_search_path to inject a path with mock libraries before the standard library search paths. This will then cause the dynamically loaded code to get compiled against a set of stub libraries instead of the actual ones.

If that is not an option, then we will need a kind of debug library, comparable to the Lua one, which allows getting and setting the bound upvalues of a function in order to patch other values in there.

@huafu
Copy link
Author

huafu commented Oct 8, 2022

If that is too complex, then I guess I'll have to improve my Typescript transformer (to make it transparent) or my test lib (to make it work also without TS) so that it loads functions to test not directly but thru a helper. This would then use module_search_path of loadstring() as you suggested to override imported stuff.

@huafu
Copy link
Author

huafu commented Oct 8, 2022

Is it normal that I can't shadow defined constants as well?

// lib.uc
const to_stub = () => "original"
function fn_to_test() {
  return to_stub();
}
export { fn_to_test };
// lib.spec.uc
import { fn_to_test } from './lib.uc';
print(call(fn_to_test, { to_stub: () => "override" })); // prints "oiriginal"

@jow-
Copy link
Owner

jow- commented Oct 8, 2022

Yes, those are local variables too.

@huafu
Copy link
Author

huafu commented Oct 8, 2022

Imported symbols act like local variables

Oh, I thought you meant local variables in the function scope, not in the global scope (ie the one holding the function). Now I understand 😄

@huafu
Copy link
Author

huafu commented Nov 29, 2022

@jow- as I mentioned before, I've just published the draft of my TypeScript to ucode compiler there - you get typings, classes and code completion for ucode thanks to typescript and some transformers. Plus the code is going thru eslint to ensure no ; or other stuffs of that kind are forgotten.
A lot more work to be done there, but it does work and having some input on what could be improved will be very welcome ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants