Hi Sava :-)
It sounds like you're making a neat little utility, maybe you can share when you're done.
I think you're stuck because of how Dana uses associative functions in the compiler for string construction. This makes it look like Dana is doing some dynamic type inference when it's unpacking string variables, but it really isn't.
Whenever I'm doing dynamic type stuff I've found it useful to keep reminding myself that Dana is a statically typed language. The dynamic type manipulation primitives are pretty powerful, and for me can easily make you think that Dana has general dynamic type support at a language level when it really doesn't.
I'll start with a quick reminder on how string variables work because I think it helps to explain your issue.
Let's say we have this program:
component provides App requires io.Output out {
int App:main(AppParam params[])
{
char str[] = "jess"
out.println("my name is: $str")
return 0
}
}What the compiler is really doing is converting the output line string to:
new char[]("my name is: ", str)(I'm assuming here you know how Dana array concatenation works)
From this you can more clearly see that your string variables must be of type char[] (or a compatible type) for this to work at all.
If you need a print something that isn't a character array, you must have access to a function which can convert it to a character array.
For an integer, you need do to e.g.:
component provides App requires io.Output out, data.IntUtil iu {
int App:main(AppParam params[])
{
char str[] = "jess"
int age = 3
out.println("my name is: $str and my age is $(iu.makeString(age))")
return 0
}
}The IntUtil.makeString() function converts to a char[] so this is OK.
Now, Dana has a feature it calls associative functions. This is where you can call a function on a primitive type or data type, if you have access to an object which has a function with a single parameter of that type.
So within the above code it would be legal to do:
char strB[] = age.makeString()
So here the compiler searches for the first named required interface which has a function called makeString() taking a single parameter of type int.
The compiler uses this technique to make string building easier. We can do this:
component provides App requires io.Output out, data.IntUtil iu {
int App:main(AppParam params[])
{
char str[] = "jess"
int age = 3
out.println("my name is: $str and my age is $age")
return 0
}
}And the compiler is going to search for a function called makeString() on a named required interface which takes a single int parameter. The compiler is then converting this to:
new char[]("my name is: ", str, " and my age is: ", iu.makeString(age))Again, everything here is a char[] so this is OK. This associative function behaviour for string variables can easily make a programmer think that Dana is doing some kind of runtime type inference, but it isn't - it's a statically-typed language. A few of my colleagues made this bad assumption before :-)
If you give a dynamically-accessed field as a string variable, Dana has no way to understand at compile-time what it's supposed to do with that field in order to turn it into a char[], so as far as I understand the compiler does nothing at all here (and couldn't do anything even if it wanted to) on the assumption the programmer knows what they're doing and the dynamic field access will already give a value of char[] type.
So, to get Dana to print out a dynamically-accessed field you have to first put it into a statically typed variable of an appropriate type, or otherwise create some way to convert that field to a char[] before giving it as a string variable.
In all of your above examples the Dana compiler will be assuming your variables are already of type char[], and the Dana runtime will be trying to interpret them as a char[], and is probably just interpreting them as a null / empty string.
Phew, what a long answer, I hope it makes a bit of sense!
jess