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

fatal: "declare -n" refs to ysh vars (as universal interface "narrow waist" to source/use ysh code) #1811

Closed
bar-g opened this issue Jan 26, 2024 · 8 comments

Comments

@bar-g
Copy link
Contributor

bar-g commented Jan 26, 2024

osh$ setvar mydict = { name: 'bob' }

osh$ declare -n var=mydict.name

osh$ echo $var

  declare -n var=$[mydict.name]
                 ^~
[ interactive ]:522: fatal: nameref 'var' contains invalid variable name 'mydict.name'
osh$ 

It almost worked already!

I'm trying to source and run some ysh code, that uses new features like dicts, and access the results with shell code that remains compatible. (The shell code checks if running in ysh to define the ysh-type access, here trying reference vars, but runs its same code with plain shell vars if not running in osh/ysh but in a real "other shell").


I want to share state between ysh modules and some remaining osh modules. Passing data isn't nice, because it's not simple to use json in osh. But accessing string variables is, and it seems to work nicely when only using string variables in the ysh parts!

But for sure, it would only be complete if osh can also access (global) ysh types (of course only at the basic string level interface).

This would allow the ysh parts to make full use of the language, while osh parts still have a defined string interface to the data, i.e. #1813 "ysh-list/dict not accessible with osh syntax (sourcing ysh procs)" and #1811 "fatal: "declare -n" refs to ysh vars (as universal interface "narrow waist" to source/use ysh code)".

@bar-g bar-g changed the title "declare -n" refs to ysh vars (as universal interface / narrow waist to source/use ysh code) fatal: "declare -n" refs to ysh vars (as universal interface / narrow waist to source/use ysh code) Jan 26, 2024
@bar-g bar-g changed the title fatal: "declare -n" refs to ysh vars (as universal interface / narrow waist to source/use ysh code) fatal: "declare -n" refs to ysh vars (as universal interface "narrow waist" to source/use ysh code) Jan 26, 2024
@andychu
Copy link
Contributor

andychu commented Jan 27, 2024

declare -n is purposely phased out! Using strings is bad!

It's unsafe because you don't know which dict is refers to. There can be multiple mydict.name at different levels of the stack.

https://www.oilshell.org/blog/2024/01/release-0.19.0.html#myvar-is-a-valueplace

value.Place does it right -- it's a (name, stack frame) tuple, so it always refers to exactly one location

@bar-g
Copy link
Contributor Author

bar-g commented Jan 27, 2024

you don't know which dict is refers to. There can be multiple mydict.name at different levels of the stack.

In shell it it's the current level, it allows to override ("shadow") a previous level, e.g. global vars, with local context values and execute the same code (i.e. function) in the local context, which is a great feature, but still with some remaining risk to override/shadow wrongly or unintentionally (strict_vars/strict_scope #1763).

In ysh it's only global or local, right? If the name ref really can't be fixed to a (possibly local) dict at execution time, e.g. with a place (thus conforming to "ysh vars are not inherited"), "declare -n" could possibly be limited to only allow name refs to global ysh variables.

"declare -n" clearly is bash/osh terrain

So, allowing name refs to ysh variables, makes osh an even more universal compat interpreter that allows to interoperate with ysh libraries if available.

@bar-g
Copy link
Contributor Author

bar-g commented Jan 28, 2024

Hm, I suppose it could work as expected if declare -n name=ysh_type_var would interpret all ysh-type vars as &ysh_type_var, i.e. creating a place if it isn't one already.

So then, the scope during execution would properly depend on the shell dynamic scope, while the name for the ysh always points to the same frame, unless a new shell "declare" or "local" execution overrides it afterwards (which is again correct in shell's dyn. scope paradigm)?

@bar-g
Copy link
Contributor Author

bar-g commented Feb 4, 2024

Would you have a better idea to define folding of List/Dict value access into compatible, ideally posix shell (not bash) syntax?

That is, some code snippets to execute in a "shell module" if running in osh/ysh that allow the remaining shell code parts to seemingly "work" with shell string variables, but actually reading and mutating ysh-typed variables that contain strings.

@andychu
Copy link
Contributor

andychu commented Feb 11, 2024

Closing, declare -n will not be enhanced for YSH, it's part of OSH only

The goal is for people to move off of it -- value.Place should do everything they need

@andychu andychu closed this as completed Feb 11, 2024
@bar-g
Copy link
Contributor Author

bar-g commented Feb 11, 2024

Would you have a better idea to define folding of List/Dict value access into compatible, ideally posix shell (not bash) syntax?

What about shvar?

shvar IFS=' x' {
  myproc
}

This seems to inject a dynamic scope variable into procs.

Is shvarGet('IFS') supposed to work in the other way, what does it?

Note I'm looking at an OSH problem and for the simplest OSH/compatible solution here, not YSH.

A solution for code parts that have to stay compatible.

Ideally just mapping "posix" string variables to YSH mutables (therfore my idea to use OSH's "declare -n", for within OSH functions only), without needing much accessor/getter/setter code for a shell compatible module to hook into YSH mutables when they are available. Otherwise, the code can just work alone (no ysh module created values mapped or copied to the string vars), the module's main code simply initializing itself and working with the same set of shell variables.

@andychu
Copy link
Contributor

andychu commented Feb 11, 2024

Sure you can use shvar, but it's not POSIX shell or bash because it takes a block. The syntax is not shell compatible.

So if you can use shvar, it seems like you can use anything else in YSH

@bar-g
Copy link
Contributor Author

bar-g commented Feb 13, 2024

So if you can use shvar, it seems like you can use anything else in YSH

When the shell compatible module runs in osh or ysh its init functions can of course make use of available ysh features in order to create a mapping between the shell variables that the rest of the compatible module is limited to use -- and the ysh mutables that all ysh modules use.

When the shell compatible module runs in another shell, though it can only use shell syntax, and only work with shell variables, so the init functions don't execute any ysh code, while the rest of the compatible module just works with compatible syntax as always.

When we get the "swimming lane" example working, I can try to add a "compatible" register_incomming_lane() function to it, to have a full example to work with.


Concerning inserting shell variables into ysh procs with shvar injected_x='$x' I haven't understood nor found an example for why and where one would need shvarGet(). Is $injected_x not working within the proc/func?

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