Initialising an associative array of struct values and string keys - initialization

(for the "D" programming language)
I've been struggling trying to initialise an associative array that has struct elements and should be index-able by a string. I would import it as a module from a separate file.
This is what I want to achieve (and it doesn't work --- I don't know if this is even possible):
mnemonic_info[string] mnemonic_table = [
/* name, format, opcode */
"ADD": {mnemonic_format.Format3M, 0x18},
...
/* NOTE: mnemonic_format is an enum type. */
/* mnemonic_info is a struct with a mnemonic_format and an ubyte */
];
Note that this works fine for arrays indexable by integers.
Optimally, I would like this to be evaluated at compile-time, as I won't be changing it. However, if it's not possible, I would be glad if you told me of the best way to build such an array at/before immediate run-time.
I need this because I'm writing an assembler.
I have searched SO and the internets for an answer, but could only find examples with integers, and other things I didn't understand or couldn't make to work.
I really like D so far but it seems hard to learn due to there not being many tutorials online.
Thanks!
On a side note: is it possible to use Tuples for associative array elements instead of a custom struct?
Edit
There is one way I found so far, but it's pretty ugly:
mnemonic_info[string] mnemonic_table;
static this() { // Not idea what this does.
mnemonic_info entry;
entry.format = mnemonic_format.Format3M;
entry.opcode = 0x18;
mnemonic_table["ADD"] = entry;
/* ... for all entries. */
}

In D, built-in associative array literals are always created in runtime, so initializing a global associative array by assigning it some value at declaration place is currently impossible.
As you found yourself, you can workaround that by assigning a value to associative array in module constructor.
The other problem in your code is struct initialization literals. You should prefer D-style struct initializers to C-style ones.
Example:
struct Foo {
int a;
string b;
}
Foo[string] global;
static this() {
global = [
"foo" : Foo(1, "hurr"),
"bar" : Foo(2, "durr")
];
}
void main() {
assert(global["foo"].a == 1);
}

Related

How to create a read-only struct without boilerplate code?

Despite the fact that Rust has absorbed many good modern programming ideas, it looks like one very basic feature is not presented.
The modern (pseudo-)functional code is based on a large number of classes of the following kind:
pub struct NamedTuple {
a: i8,
b: char,
}
impl NamedTuple {
fn new(a: i8, b: char) -> NamedTuple {
NamedTuple { a: a, b: b }
}
fn a(&self) -> i8 {
self.a
}
fn b(&self) -> char {
self.b
}
}
As you can see, there is a lot of boilerplate code here. Is there really no way to describe such types compactly, without a boilerplate code?
When you have boilerplate, think macros:
macro_rules! ro {
(
pub struct $name:ident {
$($fname:ident : $ftype:ty),*
}
) => {
pub struct $name {
$($fname : $ftype),*
}
impl $name {
fn new($($fname : $ftype),*) -> $name {
$name { $($fname),* }
}
$(fn $fname(&self) -> $ftype {
self.$fname
})*
}
}
}
ro!(pub struct NamedTuple {
a: i8,
b: char
});
fn main() {
let n = NamedTuple::new(42, 'c');
println!("{}", n.a());
println!("{}", n.b());
}
This is a basic macro and could be extended to handle specifying visibility as well as attributes / documentation on the struct and the fields.
I'd challenge that you have as much boilerplate as you think you do. For example, you only show Copy types. As soon as you add a String or a Vec to your structs, this will fall apart and you need to either return a reference or take self.
Editorially, I don't think this is good or idiomatic Rust code. If you have a value type where people need to dig into it, just make the fields public:
pub struct NamedTuple {
pub a: i8,
pub b: char,
}
fn main() {
let n = NamedTuple { a: 42, b: 'c' };
println!("{}", n.a);
println!("{}", n.b);
}
Existing Rust features prevent most of the problems that getter methods attempt to solve in the first place.
Variable binding-based mutability
n.a = 43;
error[E0594]: cannot assign to field `n.a` of immutable binding
The rules of references
struct Something;
impl Something {
fn value(&self) -> &NamedTuple { /* ... */ }
}
fn main() {
let s = Something;
let n = s.value();
n.a = 43;
}
error[E0594]: cannot assign to field `n.a` of immutable binding
If you've transferred ownership of a value type to someone else, who cares if they change it?
Note that I'm making a distinction about value types as described by Growing Object-Oriented Software Guided by Tests, which they distinguish from objects. Objects should not have exposed internals.
Rust doesn't offer a built-in way to generate getters. However, there are multiple Rust features that can be used to tackle boilerplate code! The two most important ones for your question:
Custom Derives via #[derive(...)] attribute
Macros by example via macro_rules! (see #Shepmaster's answer on how to use those to solve your problem)
I think the best way to avoid boilerplate code like this is to use custom derives. This allows you to add a #[derive(...)] attribute to your type and generate these getters at compile time.
There is already a crate that offers exactly this: derive-getters. It works like this:
#[derive(Getters)]
pub struct NamedTuple {
a: i8,
b: char,
}
There is also getset, but it has two problems: getset should have derive in its crate name, but more importantly, it encourages the "getters & setters for everything" anti pattern by offering to also generate setters which don't perform any checks.
Finally, you might want to consider rethinking your approach to programming in Rust. Honestly, from my experience, "getter boilerplate" is hardly a problem. Sure, sometimes you need to write getters, but not "a large number" of them.
Mutability is also not unidiomatic in Rust. Rust is a multi paradigm language, supporting many styles of programming. Idiomatic Rust uses the most useful paradigm for each situation. Completely avoiding mutation might not be the best way to program in Rust. Furthermore, avoiding mutability is not only achieved by providing getters for your fields -- binding and reference mutability is far more important!
So, use read-only access to fields where it's useful, but not everywhere.

Will an array of pointers be equal to an array of chars?

I have got this code:
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
char [] *str_ptr;
writeln(str_ptr);
str_ptr = &str;
*(str_ptr[0].ptr) = 'f';
writeln(*str_ptr);
writeln(str_ptr[0][1]);
}
I thought that I am creating an array of pointers char [] *str_ptr so every single pointer will point to a single char. But it looks like str_ptr points to the start of the string str. I have to make a decision because if I am trying to give access to (for example) writeln(str_ptr[1]); I am getting a lot of information on console output. That means that I am linking to an element outside the boundary.
Could anybody explain if it's an array of pointers and if yes, how an array of pointers works in this case?
What you're trying to achieve is far more easily done: just index the char array itself. No need to go through explicit pointers.
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
str[0] = 'f';
writeln(str[0]); // str[x] points to individual char
writeln(str); // faa
}
An array in D already is a pointer on the inside - it consists of a pointer to its elements, and indexing it gets you to those individual elements. str[1] leads to the second char (remember, it starts at zero), exactly the same as *(str.ptr + 1). Indeed, the compiler generates that very code (though plus range bounds checking in D by default, so it aborts instead of giving you gibberish). The only note is that the array must access sequential elements in memory. This is T[] in D.
An array of pointers might be used if they all the pointers go to various places, that are not necessarily in sequence. Maybe you want the first pointer to go to the last element, and the second pointer to to the first element. Or perhaps they are all allocated elements, like pointers to objects. The correct syntax for this in D is T*[] - read from right to left, "an array of pointers to T".
A pointer to an array is pretty rare in D, it is T[]*, but you might use it when you need to update the length of some other array held by another function. For example
int[] arr;
int[]* ptr = &arr;
(*ptr) ~= 1;
assert(arr.length == 1);
If ptr wasn't a pointer, the arr length would not be updated:
int[] arr;
int[] ptr = arr;
ptr ~= 1;
assert(arr.length == 1); // NOPE! fails, arr is still empty
But pointers to arrays are about modifying the length of the array, or maybe pointing it to something entirely new and updating the original. It isn't necessary to share individual elements inside it.

How to create a generic function to take hashtable name and a struct as parameters in a kernel module?

I'm currently writing a kernel module which uses multiple hashtables to store different structures. How would I go about implementing a single generic function which would take the hashtable name, hash key and structure to be stored as parameters and do the corresponding store operation?
Here is my hashtable and structure definition.
static DEFINE_HASHTABLE(count, 7);
struct mystruct {
int data ;
struct hlist_node my_hash_list ;
};
Here is my store code ( I seem to be getting a null pointer error if I increment temp->data directly instead of doing it my roundabout add and del way :( )
struct mystruct *temp;
struct mystruct *first;
temp = kmalloc(sizeof(struct mystruct),GFP_KERNEL);
first = kmalloc(sizeof(struct mystruct),GFP_KERNEL);
hash = command;
hash_for_each_possible(count, temp, my_hash_list,hash){
first->data=temp->data+1;
printk("Count: %d\n",first->data);
hash_add(count, &(first->my_hash_list), hash);
hash_del(&(temp->my_hash_list));
return;
}
first->data=1;
hash_add(count, &(first->my_hash_list), hash);
This is for the count hashtable and mystruct structure. Is it possible to create a kernel module function to have a placeholder pointer to any structure and kmalloc memory to that struct? Also how to pass the hashtable name as a parameter?
You cannot create a function which accepts name of the hashtable: it is prohibited by C language. So, your function may only accept a pointer to the hashtable. But because it accepts a pointer, you may no longer use macros like hash_add, which requires name.
You have 2 possibilites:
Creating function-like macro, so it can accept hashtable name, structure and other definitions.
This way is commonly used by Linux kernel, which tends to be fast. Note, that operations like hash_add, hash_for_each_possible are macros too.
Wrap hashtable into your own structure. Into the same structure you need to add all additional information about hash elements: size (for kmalloc), getter of the key from the element (for search) and setter for it(for inserter), and so on.
Something like
struct my_hashtable {
DECLARE_HASHTABLE(count, 7);
size_t obj_size;
unsigned long (*get_key)(void* obj);
void (*set_key)(void* obj, unsigned long key);
};

go tour when to not use pointer to struct literal in a variable

Per the Go tour page 28 and page 53
They show a variable that is a pointer to a struct literal. Why is this not the default behavior? I'm unfamiliar with C, so it's hard to wrap my head around it. The only time I can see when it might not be more beneficial to use a pointer is when the struct literal is unique, and won't be in use for the rest program and so you would want it to be garbage collected as soon as possible. I'm not even sure if a modern language like Go even works that way.
My question is this. When should I assign a pointer to a struct literal to a variable, and when should I assign the struct literal itself?
Thanks.
Using a pointer instead of just a struct literal is helpful when
the struct is big and you pass it around
you want to share it, that is that all modifications affect your struct instead of affecting a copy
In other cases, it's fine to simply use the struct literal. For a small struct, you can think about the question just as using an int or an *int : most of the times the int is fine but sometimes you pass a pointer so that the receiver can modify your int variable.
In the Go tour exercises you link to, the Vertex struct is small and has about the same semantic than any number. In my opinion it would have been fine to use it as struct directly and to define the Scaled function in #53 like this :
func (v Vertex) Scaled(f float64) Vertex {
v.X = v.X * f
v.Y = v.Y * f
return v
}
because having
v2 := v1.Scaled(5)
would create a new vertex just like
var f2 float32 = f1 * 5
creates a new float.
This is similar to how is handled the standard Time struct (defined here), which is usually kept in variables of type Time and not *Time.
But there is no definite rule and, depending on the use, I could very well have kept both Scale and Scaled.
You're probably right that most of the time you want pointers, but personally I find the need for an explicit pointer refreshing. It makes it so there's no difference between int and MyStruct. They behave the same way.
If you compare this to C# - a language which implements what you are suggesting - I find it confusing that the semantics of this:
static void SomeFunction(Point p)
{
p.x = 1;
}
static void Main()
{
Point p = new Point();
SomeFunction(p);
// what is p.x?
}
Depend on whether or not Point is defined as a class or a struct.

Problems with a structure copy

I am having a compiler issue in Visual Studio 2005 using the standard C compiler when trying to do a structure copy from one location to another.
The types are defined in a file as follows:
definition.h
#define MAX 7
typedef struct{
char recordtext[18];
boolean recordvalid;
}recordtype;
typdef recordtype tabletype[MAX];
typedef struct{
tabletype table;
}global_s;
Let us pretend that a global_s "object" is instantiated and initialized somewhere and a pointer to this structure is created.
#include "definition.h"
global_s global;
global_s* pglobal = &global;
init(&pglobal);
Meanwhile, in another file (and this is where my problem is) i am trying to create a local tabletype object, and fill it with the global table member, using a get method to protect the global (lets pretend it is "static")
#include "definition.h"
extern global_s* pglobal;
tabletype t;
gettable(&t);
void gettabl (tabletype* pt)
{
*pt = pglobal->table;
}
When I go to compile, the line in the gettable function throws a compiler error "error C2106: '=': left operand must be l-value. It looks as though this should behave as a normal copy operation, and in fact if I perform a similar operation on a more basic structure I do not get the error. For example If I copy a structure only containing two integers.
Does anyone have a solid explanation as to why this operation seems to be incorrect?
(Disclaimer: I have developed this code as a scrubbed version of my actual code for example purposes so it may not be 100% correct syntactically, I will edit the question if anyone points out an issue or something needs to be clarified.)
It's the arrays in the struct; they cannot be assigned. You should define an operator=() for each of the structs, and use memcpy on the arrays, or copy them in a loop element by element.
(IF you want to get a reference to your global variable):
I am not sure, if this is correct (and the problem), but I think besides function prototypes, arrays and pointers (to arrays 1. element) are NOT exactly the same thing. And there is a difference between pointer to array and pointer to the 1. element of an array)
Maybe taking the adress of the array:
*pt = &(pglobal->table);
Anyway it might be better not to fetch the address of the whole array but the address of the first element, so that the resulting pointer can be used directly as record array (without dereferencing it)
recordtype* gettable (size_t* puLength)
{
*puLength = MAX;
return &(pglobal->table[0]);
}
(IF you want a copy of the table):
Arrays can't be copied inplace in C90, and of course you have to provide target memory. You would then define a function get table like this:
void gettable (recordtype * const targetArr)
{
size_t i = 0;
for (; i < MAX; i++) targetArr[i] = pglobal->table[i];
return;
}
an fully equivalent function prototype for gettable is:
void gettable(recordtype[] targetArr);
Arrays are provided by refernce as pointer to the first element, when it comes to function parameters. You could again ask for an pointer to the whole array, and dereference it inside gettable. But you always have to copy elementwise.
You can use memcopy to do the job as 1-liner. Modern compilers should generate equally efficent code AFAIK.

Resources