in my verification environment I have 3 different registers with the same fields: load_0, load_1 and load_2.
Now I have the same function duplicated 3 times for every register and differs only in one line:
duplicated_func_0() {
value = timer_regs.load_0; //This is the only different line (in duplicated_func_1 - load_1 is substituted
...
};
Is there a better way to access variable name (that differs only by its index) than duplicate the same function 3 times?
Something like this:
not_duplicated_func(index : uint) {
value = timer_regs.load_%x; //Is there a way to put the input index in the variable name instead of %x?
};
I will appreciate any help you can provide.
Inside timer_regs I wouldn't define 3 variables, load_0, load_1 and load_2, but a list of the respective type:
extend TIMER_REGS vr_ad_reg_file {
loads[3] : list of TIMER_LOAD vr_ad_reg;
};
This way you can access each register by index.
If you can't change the layout you already have, just constrain each list item to be equal to your existing instances:
extend TIMER_REGS vr_ad_reg_file {
loads[3] : list of TIMER_LOAD vr_ad_reg;
keep loads[0] == load_0;
keep loads[1] == load_1;
keep loads[2] == load_2;
};
Related
I am making a weather application. I basically created a class where I will only get data from API and return them as needed. I have variables like cityName, currentWeather etc.
Problem is sometimes API doesn't provide them all so I need to check if they are nil or not before return them. What comes to my mind is set variables like this first:
private var cityNamePrivate: String!
and then
var cityNamePublic: String {
if cityNamePrivate == nil {
//
}
else { return cityNamePrivate }
But as you can as imagine, its very bad because I have a lots of variables. Is there any better logic for this? Should I just return them and check later in wherever I send them?
The problem here is that you will have many variables to deal with. It's not just returning them from the API, it's also dealing with them in your app and perhaps in some processing code.
One solution is to have a big class or struct with many properties. This will work very well, is straightforward to implement but will require lots of repetitive code. Moreover, it will require to change your API and all your code, whenever some new properties are made available by the remote web service.
Another approach is to have replace the big inflexible class or struct, with a dynamic container, e.g. an array of items [ Item ] or a dictionary that associates names to items [ String : Item ]. If the data is just strings, it's straightforward. If it's several types, you may have to have to implement a small type system for the elements. Example:
var x : [ String: String] = [:]
x["city"]="Strasbourg"
x["temperature"]="34°C"
struct Item {
var name : String
var value : String
}
var y : [ Item ] = [Item(name:"city",value:"Strasbourg"),
Item(name:"temperature", value:"34°C")]
The other advantage of this approach is that you stay loyal to the semantics: an information that is not available in the API (e.g. "unknown") is not the same as a default value. I.e. if the weather API does not return a temperature, you will not display 0 in your app. because 0 is not the same as "unknown". While strings are more robust in this matter, the absence of a name is not the same as an empty name.
This last remark suggests that in your current scheme, of having a big data transfer object, you should consider to keep the properties as optional, and move the responsibility for the processing of unknown data to your app.
With arrays you can use a subscript to access Array Elements directly. You can read or write to them. With Sets I am not sure of a way to write its Elements.
For example, if I access a set element matching a condition I'm only able to read the element. It is passed by copy and I can't therefore write to the original.
For example:
columns.first(
where: {
$0.header.last == Character(String(i))
}
)?.cells.append(value: addValue)
// ERROR: Cannot use mutating member on immutable value: function call returns immutable value
You can't just change things inside a set, because of how a (hash) set works. Changing them would possibly change their hash value, making the set into an invalid state.
Therefore, you would have to take the thing you want to change out of the set, change it, then put it back.
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
columns.remove(thing)
thing.cells.append(value: addValue)
columns.insert(thing)
}
If the == operator on Column doesn't care about cells (i.e. adding cells to a column doesn't suddenly make two originally equal columns unequal and vice versa), then you could use update instead:
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
thing.cells.append(value: addValue)
columns.update(thing)
}
As you can see, it's quite a lot of work, so maybe sets aren't a suitable data structure to use in this situation. Have you considered using an array instead? :)
private var _columns: [Column]
public var columns : [Column] {
get { _columns }
set { _columns = Array(Set(newValue)) }
// or any other way to remove duplicate as described here: https://stackoverflow.com/questions/25738817/removing-duplicate-elements-from-an-array-in-swift
}
You are getting the error because columns might be a set of struct. So columns.first will give you an immutable value. If you were to use a class, you will get a mutable result from columns.first and your code will work as expected.
Otherwise, you will have to do as explained by #Sweeper in his answer.
I've searched a lot but can't find a clear answer anywhere for string list -> enum.
I've got a list of strings that I want to turn into an enum that I can select from in Unity inspector.
Specifically, I'm trying to make an enum list of all the currently set-up Input buttons from project settings. I've got all the names, just don't know how to make it an enum or similar. Ideally showing up like a KeyCode variable in inspector.
Currently trying (and failing) with:
foreach (string s in names)
{
if (Enum.TryParse(s, true, out list))
Debug.Log(list);
else Debug.Log("FAILED");
}
"names" = static List<string> names;
"list" = static MyList list;
"MyList" = enum MyList { Null }
Returns "FAILED" 58 times for only 29 Input axis.
I want a simple solution, so if its not possible or relatively simple, I'll work out something else.
Code for getting the "names" list of strings (Works correctly):
var inputManager = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset")[0];
SerializedObject obj = new SerializedObject(inputManager);
SerializedProperty axisArray = obj.FindProperty("m_Axes");
if (axisArray.arraySize == 0)
Debug.Log("No Axes");
for (int i = 0; i < axisArray.arraySize; ++i)
{
var axis = axisArray.GetArrayElementAtIndex(i);
var name = axis.FindPropertyRelative("m_Name").stringValue;
names.Add(name);
}
Normally you can do
foreach (string colorName in Enum.GetNames(typeof(Colors))) which will iterate the names of the enums.
In your code above you havent shown what list is, nor where names has come from. However.
enum Things
{
Item1 = 0,
Item2 = 1
}
You can get the name from string name = Enum.GetName(typeof(Things), (int)Things.Item2) and you can get values from names with int value = (int)Enum.Parse(typeof(Things), nameOfThing)
So depending on what you actually want in a list and what you start with, iterate through and pick the relevant one
I ended up making my own solution, since (and please correct me if I'm wrong) the TryParse() and Parse() methods appear to need the enum to already contain entries with the same name (or index int) as the string to parse. This defeats the purpose for me, since I am doing this because I don't have the names in there already.
My solution ended up being to switch to having a single string input variable instead of an enum, then use Odin Inspector's ValidateInput attribute to check (for spelling errors, and) if the input variable matches any of the string entries in my dynamic list of InputManager input names (which I update manually using Odin Inspector's Button attribute and the code in the original post).
It's slightly less clean than I wanted, but does the job, so I'm satisfied.
I am trying to constrain my list items to be equal to certain values under certain conditions.
For that I have devised a define as computed macro that
define <num_prob_constraints'struct_member> "CHECK_and_SET_CONSTRAINTS <lst'exp>" as computed {
//var cur : list of uint = <lst'exp>.as_a(list of uint);
var t : uint = <lst'exp>.as_a(list of uint).size();
print t;
for i from 1 to 4 {
result = append(result,"keep ",<lst'exp>,"[",i,"]==",i,"=> ",<lst'exp>,"[",i,"]==389; \n");
};
};
and in my code I use this macro like this:
struct schedule{
n : uint;
sched_w : list of list of int;
CHECK_and_SET_CONSTRAINTS sched_w;
};
But this does not work. First, it prints some random size (From the macro) instead of the list’s real size.
Secondly, I get errors of this sort:
*** Error: '1' is of type 'int', while expecting type 'list of int'.
in code generated by macro defined at line 3 in
sports_sched_macro.e
keep sched_w[1]==1=> sched_w[1]==389;
expanded at line 8 in sports_sched.e
CHECK_and_SET_CONSTRAINTS sched_w;
Any ideas on what is wrong here?
Macros are simply code substituts. Their function is simply to replace some string with another (calculated or not) during the parsing phase.
This means that the macro will be deployed where you used it in the parsing phase which precedes the generation phase. So, in fact, the list does not exist yet, and you cannot access it’s size and items.
More specifically, your macro is deployed this way:
struct schedule {
n : uint;
sched_w : list of list of int;
keep sched_w[1]==2=> sched_w[1]==389;
keep sched_w[2]==2=> sched_w[2]==389;
...
...
};
The error message you received tell you that you cannot access specific list items explicitly (since the list size and item’s values are yet undetermined).
If you want to keep your list with size 4, and if the value is 2 you want to replace it with 389, you may need to use the post_generate() method, as you are trying to access values that are already assigned to the list items:
keep sched_w.size()==4;
post_generate() is also{
for each in sched_w {
if (it==2) {it=389};
};
};
Are you sure you want to constrain a 2-dimensional list? This looks a bit different. E.g. for an array schedule[4][1]:
schedule: list of list of int;
keep schedule.size() == 4;
keep for each (sublist) in schedule {
sublist.size() == 1;
for each (elem) in sublist {
...
};
};
I am currently using ReSharper V8.1. I've only recently began using ReSharper and have found some interest in their LiveTemplate Macros. I've conjured up a solution to return a list of HotspotItems from a constant, similar to ReSharper's predefined macro "Comma-delimited list of values". In the method I take the constant variable of the template parameter and do a split string on them to provide a collection of HotSpotItems. Unfortunately it doesn't work if I use the macro more than one time within a template. Below is an extreme hack job showing my implementation of the method HotspotItems of IMacroImplementation.
I am hoping that someone out there may have done some work in this area and could possibly provide an example of how they've implemented IMacroImplementation which provides a list of items from a constant and also allows for multiple uses within a single template.
Thank you.
public override HotspotItems GetLookupItems(IHotspotContext context)
{
HotspotItems hotSpotItems = null;
foreach (var hotspot in context.HotspotSession.Hotspots)
{
if (hotspot.Expression != null && ((MacroCallExpressionNew)hotspot.Expression).Definition is Macros.DisplayMultipleItems)
{
//hotspot.CurrentValue
var multiItems = ((MacroCallExpressionNew) hotspot.Expression).Definition as DisplayMultipleItems;
if (!multiItems.ItemSet)
{
var expression = hotspot.Expression as MacroCallExpressionNew;
IMacroParameterValueNew baseValue = expression.Parameters[0].GetValue(context.SessionContext.Solution.GetLifetime(), context.HotspotSession);
string templateValue = baseValue.GetValue();
multiItems.ItemSet = true;
if (!string.IsNullOrEmpty(templateValue) && templateValue.Split(',').Any())
{
var lookupItems = templateValue.Split(',').Select(param => new TextLookupItem(param)).Cast<ILookupItem>().ToList();
if (hotSpotItems == null)
hotSpotItems = new HotspotItems(lookupItems);
else
{
foreach (var item in lookupItems)
{
hotSpotItems.Items.Add(item);
}
}
}
}
}
}
return hotSpotItems;
}
You should fire up dotPeek and point it to the ReSharper bin directory and take a look at ListMacroDef and ListMacroImpl, which is the implementation for the comma-delimited list macro.
The definition derives from SimpleMacroDefinition. It gets given the parameters in the call to GetPlaceholder, looks at the first and splits it by comma, returning the first item as the placeholder.
ListMacroImpl is just as simple. Its constructor has an [Optional] parameter of type MacroParameterValueCollection. This is the list of parameter values specified in the hotspot editor. You'll want to check for null and take the first parameter, which will be your delimited list. It then overrides GetLookupItems and returns HotspotItems.Empty if the parameter value is null, or parses the value and returns a list of TextLookupItem.
You don't need to look at the session and list of hotspots - that will get you all hotspots in the session, when you're only interested in the current hotspot, and ReSharper will create a new IMacroImplementation for each hotspot and give you those values in your constructor.