Specman e: How to use deep_copy on list of structs? - deep-copy

I have a my_list_1 (list of structs) that defined this way:
struct my_struct {
something[2] : list of int;
something_else[2] : list of uint;
};
...
my_list_1[10] : list of my_struct;
I need to copy this list to a local variable in a method:
foo_method() is {
var my_list_2 : list of my_struct;
my_list_2 = deep_copy(my_list_1);
...
};
The compilation error I get:
*** Error: 'my_list_1' is of type 'list of my_struct', while
expecting type 'any_struct'.
...
my_list_2 = deep_copy(my_list_1);
All variations to write deep_copy() I've tried caused compilation error... How to copy a list of structs to a local variable? Thank you for your help.

You can't use deep_copy(...) directly to copy a list. If you look in the docs, deep_copy(...) takes a single parameter of type any_struct and returns a single struct instance. You have to use it in a for each loop:
extend sys {
my_list_1[10] : list of my_struct;
run() is also {
foo_method();
};
foo_method() is {
var my_list_2 : list of my_struct;
for each (elem) in my_list_1 {
my_list_2.add(deep_copy(elem));
};
print my_list_1[0], my_list_2[0];
print my_list_1[1], my_list_2[1];
};
};

From Specman 14.2, deep_copy() will copy anything. I think it is not yet out, but due towards the end of this year.

Related

Mapping between structs in a loop

I have a function that does some mapping between 2 structs:
Struct1 => Struct2
where Struct1 is as follows:
type Struct1 struct {
A Transaction `json:"transaction"`
B string `json:"name"`
...
}
whereas Struct2 looks like this:
type Struct2 struct {
C AnotherTransaction `json:"transaction"`
D string `json:"name"`
...
}
I have a function that maps the "inner" type Transaction => AnotherTransaction, but the issue I have is that there is an outer Struct, named Struct3 for convenience, that is as follows:
type Struct3 struct {
Failed []Struct2 `json:"failed"` // a list of transactions
Success []Struct2 `json:"success"`
}
func mapTo(st3 Struct3) Struct1 {
st1 := Transaction{}
// the mapping between A => C is quite lengthy
st1.someField = st3.struct2.anotherField
return st1 // now mapped
}
My issue is that from Struct3 I need to access each element of Struct2 and fire up the mapping function above, but I am not sure how to go about it. How can I loop through each element of []Struct2 append each element and return Struct3 now populated with the mapping from mapTo()?
You can update the map function's argument to struct2 and loop through the struct3's fields of array from main function and send each of them to the toMap function.
func main() {
type Struct3 struct {
Failed []Struct2 `json:"failed"` // a list of transactions
Success []Struct2 `json:"success"`
}
s3 := &Struct3{
Failed: make([]Struct2, 0),
Success: make([]Struct2, 0),
}
for i := range s3.Success {
// do something with the result value
_ = toMap(s3.Success[i])
}
for i := range s3.Failed {
// do something with the result value
_ = toMap(s3.Failed[i])
}
}
func mapTo(st2 Struct2) Struct1 {
st1 := Transaction{}
// the mapping between A => C is quite lengthy
st1.someField = st2.anotherField
return st1 // now mapped
}

How to process array items given in YAML to associate with a struct in Go?

I have not found a way to allocate values defined in an array within a YAML file field to the fields of a struct in Go. I am already unmarshalling the whole file to a defined struct, but I would like to go deeper.
The YAML file is a hardcoded file.
YAML File
- id : [apples,bananas]
fruits: true
vegetables: false
- id : [apples,onions]
fruits: true
vegetables: true
Go structs
type Basket struct {
ID RawID `yaml:"id"`
Content BasketContent
}
type RawID struct {
Apples bool `yaml:"apples"`
Bananas bool `yaml:"bananas"`
Onions bool `yaml:"onions"`
}
type BasketContent struct {
Fruits boolean `yaml:"fruits"`
Vegetables boolean `yaml:"vegetables"`
}
I am expecting to identify which elements are located in the id field, to later hash them into a value.
You could try the following package that has definitions of yaml to structs
https://github.com/go-yaml/yaml
This includes documentation on how to handle arrays.
Edit 1: Including relevant code snippet
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}

To create map of array of map in golang

I want to create a json in golang for which I need to first create map of the following:
{"inputs": [{"data": {"image": {"url": "SOME_URL"}}}]}
how to create this map on golang. (for now even hardcoded will also work for me)
In a struct:
type SomeData struct {
Inputs []struct {
Data struct {
Image struct {
URL string `json:"url"`
} `json:"image"`
} `json:"data"`
} `json:"inputs"`
}
But if we wanted to be able to add things individually, AND be more idiomatic, we would do it like this:
type Image struct {
URL string `json:"url"`
}
type Data struct {
Image Image `json:"image"`
}
type Input struct {
Data Data `json:"data"`
}
type SomeData struct {
Inputs []Input `json:"inputs"`
}
Then, of course, we could always just use a map:
someData := map[interface{}]interface{}{}
It really just depends on which route you'd like to go. I suggest the second one as it gives you better fine-grained tooling without any pesky dirty tricks or code-clutter.
Hope this helps!
neededMap := make(map[string][]map[string]map[string]map[string]string)

cannot invoke 'append' with an argument list of type '(T)'

Just got this strange error when trying to write a stack with generic type in latest playground.
I really don't understand what's wrong here, can someone explain to me why I got this error?
class MyStack<T> {
var stack1 = [T]()
func push<T>(value: T) {
stack1.append(value) // Error: cannot invoke 'append' with an argument list of type '(T)'
}
}
The class is already generic, no need to make push generic too
class MyStack<T> {
var stack1 = [T]()
func push(value: T) {
stack1.append(value)
}
}
When push is declared as push<T>, the generic parameter overrides the one defined on the class. So, if we were to rename the generic parameters, we'd get
class MyStack<T1> {
var stack1 = [T1]()
func push<T2>(value: T2) {
stack1.append(value) // Error: cannot invoke 'append' with an argument list of type '(T2)'
}
}
presented like this, it makes sense that we cannot push a T2 in [T1].

does specman have static variables?

I have the following code in specman that I inherited:
some_method() is {
var a: bool;
if (!a) {
a = some_other_method();
};
};
My understanding is that each time some_method() is called, a is generated anew, and there's no sense in checking a's value before it's assigned. However, it may be that I'm missing something here. For instance, if a is static then this code makes sense, which brings me to my question:
Is there any way for a variable to be static in specman?
there are no static variables as in C. A variable in a method has its default value (False in this case) if not initialized, so you should be right if (!a) should always be True.
Things would be different if a was a struct member, then like in other OO languages it would retain there value over several method calls and the check would make more sense:
struct some_struct_s {
a : bool;
some_method() is {
if (!a) {
a = some_other_method();
};
};
};
You can check stuff like this also on the interactive prompt:
Specman> var a : bool;
Specman> print a
a = FALSE
There the interactive help is also nice, for example try:
Specman> help variable
and select the entry (by number) sn_eref: variables : declaring. There you will find all relevant information for your question.
Cheers,
Daniel
Static struct members (events, fields, methods) were added to the language in Specman v15.2. A static field can't be generated, physical(%) or used in when subtypes.
struct some_struct_s {
a : bool;
some_method() is {
if (!a) {
a = some_other_method();
};
};
};
-- Change field 'a' for all instances
on xxx { some_struct_s::a = TRUE; };
Here's some comments from the teamspecman blog : Static members in e

Resources