Get the name of a class and method as a string - rascal

To get the name of a project as a string I can use:
loc project = |project://Test/|;<br/>
str name = project.authority;
Is there something similar available for classes or methods?
I would like to write the contents of a class/method to disk and then use its name as the filename.

To answer my own question, I needed to use;
public void testcode( loc project){
M3 model = createM3FromEclipseProject(project);
for (loc l <- classes(model)) {
println(l.path);
}
Sorry, didn't read the docs thoroughly.

Related

DXL ignoring the error if an attribute doesn't exist in a module

I am writing some DXL for use as a DXL column that for each object in a module, looks at the in-links and returns the link name. Then if the link name starts with "verif", it will get the object text from an attribute "TestResultFloating" in the linked module and show it in the current module, in the DXL column.
The problem I will have when I use this on the whole database (currently I am just using a sandbox) is that some of the modules linked through the "verif" link module will not contain the "TestResultFloating" attribute. For these I would like to oppress the 'unknown Object attribute (TestResultFloating)' error and instead display something like N/A for that Object in the current module.
Below is my code that currently works as long as the "TestResultFloating" attribute is present in the linked module, but will throw the error if the attribute is not present.
ModName_ mSrc
Object o = current
Object nObject
Object oSrc, oDest
LinkRef lr = null
Link l = null
string linkname = ""
string attrbName = "TestResultFloating"
for mSrc in (obj <- "*") do {
if (!open(mSrc)) {
read(fullName(mSrc), true)
}
}
for l in (obj <- "*") do {
oSrc = source(l)
linkname = name(module(l))
string linkmodname = upper(linkname[0:4])
if(linkmodname == "VERIF") {
string objText = oSrc."TestResultFloating"
display(objText)
}
}
I tried one way of doing it which I got from the dxl reference manual which was to check whether the attribute exists and then do the operation. This is what I added but it doesn't seem to work, I still get the same error "unknown Object attribute (TestResultFloating)"
What I tried is shown below:
if(linkmodname == "VERIF") {
if(exists attribute "TestResultFloating"){
string objText = oSrc."TestResultFloating"
display(objText)
}
else {
display("N/A")
}
}
Please also note that i'm very new to DOORS and DXL so if I am doing something drastically wrong or I am asking a simple question please forgive me.
There is a utility function called string probeAttr_(Object o, string attrName) that can be used for getting an attribute value if you are not sure whether the attribute is readable or whether it even exists.
This function and a lot of similar functions tailored for different circumstances can be found in the file "c:\Program Files\IBM\Rational\DOORS\9.6\lib\dxl\utils\attrutil.inc"

M3 model#uses: src to innerclass

Is there an easy way to translate the "src" loc of model#uses to a class?
The problem I am having is I tried to use the model#declarations to match and find the class by location, but matching between file:// and project:// (m3 model) is not 100% pure (ignoring .scheme), comparing
begin.line >=
and
end.line <=
still results in 2 classes, when a "src" line is in the innerclass.
To summarise: Is there a function that returns the class, e.g.
loc classLoc = getClass( |home:///Workspaces/Rascal/src/Fruit.java|(150,1,<11,12>,<11,13>) );
That will return |java+class://Fruit|, having line 11 be a line in class Fruit.
Sure. Consider this example Java code:
public abstract class Fruit {
private class X {
}
int main() {
X x = new X();
return 1;
}
}
and consider I stored the M3 model in m and take the use of X located at this source location l = |home:///Workspaces/Rascal/rascal/src/org/rascalmpl/courses/example-project/src/Fruit.java|(150,1,<11,12>,<11,13>);
Then this expression will tell you to which declaration the class points to:
rascal>cl = m#uses[l];
set[loc]: {|java+class:///Fruit/X|}
To find out in which other class this class is then nested we invert the containment relation and look up the parent of the nested class like so:
rascal>m#containment<to,from>[cl]
set[loc]: {|java+class:///Fruit|}

How can I use a HashMap of List of String in Vala?

I am trying to use a HashMap of Lists of strings in Vala, but it seems the object lifecycle is biting me. Here is my current code:
public class MyClass : CodeVisitor {
GLib.HashTable<string, GLib.List<string>> generic_classes = new GLib.HashTable<string, GLib.List<string>> (str_hash, str_equal);
public override void visit_data_type(DataType d) {
string c = ...
string s = ...
if (! this.generic_classes.contains(c)) {
this.generic_classes.insert(c, new GLib.List<string>());
}
unowned GLib.List<string> l = this.generic_classes.lookup(c);
bool is_dup = false;
foreach(unowned string ss in l) {
if (s == ss) {
is_dup = true;
}
}
if ( ! is_dup) {
l.append(s);
}
}
Note that I am adding a string value into the list associated with a string key. If the list doesn't exist, I create it.
Lets say I run the code with the same values of c and s three times. Based some printf debugging, it seems that only one list is created, yet each time it is empty. I'd expect the list of have size 0, then 1, and then 1. Am I doing something wrong when it comes to the Vala memory management/reference counting?
GLib.List is the problem here. Most operations on GLib.List and GLib.SList return a modified pointer, but the value in the hash table isn't modified. It's a bit hard to explain why that is a problem, and why GLib works that way, without diving down into the C. You have a few choices here.
Use one of the containers in libgee which support multiple values with the same key, like Gee.MultiMap. If you're working on something in the Vala compiler (which I'm guessing you are, as you're subclassing CodeVisitor), this isn't an option because the internal copy of gee Vala ships with doesn't include MultiMap.
Replace the GLib.List instances in the hash table. Unfortunately this is likely going to mean copying the whole list every time, and even then getting the memory management right would be a bit tricky, so I would avoid it if I were you.
Use something other than GLib.List. This is the way I would go if I were you.
Edit: I recently added GLib.GenericSet to Vala as an alternative binding for GHashTable, so the best solution now would be to use GLib.HashTable<string, GLib.GenericSet<string>>, assuming you're okay with depending on vala >= 0.26.
If I were you, I would use GLib.HashTable<string, GLib.HashTable<unowned string, string>>:
private static int main (string[] args) {
GLib.HashTable<string, GLib.HashTable<unowned string, string>> generic_classes =
new GLib.HashTable<string, GLib.HashTable<unowned string, string>> (GLib.str_hash, GLib.str_equal);
for (int i = 0 ; i < 3 ; i++) {
string c = "foo";
string s = i.to_string ();
unowned GLib.HashTable<unowned string, string>? inner_set = generic_classes[c];
stdout.printf ("Inserting <%s, %s>, ", c, s);
if (inner_set == null) {
var v = new GLib.HashTable<unowned string, string> (GLib.str_hash, GLib.str_equal);
inner_set = v;
generic_classes.insert ((owned) c, (owned) v);
}
inner_set.insert (s, (owned) s);
stdout.printf ("container now holds:\n");
generic_classes.foreach ((k, v) => {
stdout.printf ("\t%s:\n", k);
v.foreach ((ik, iv) => {
stdout.printf ("\t\t%s\n", iv);
});
});
}
return 0;
}
It may seem hackish to have a hash table with the key and value having the same value, but this is actually a common pattern in C as well, and specifically supported by GLib's hash table implementation.
Moral of the story: don't use GLib.List or GLib.SList unless you really know what you're doing, and even then it's generally best to avoid them. TBH we probably would have marked them as deprecated in Vala long ago if it weren't for the fact that they're very common when working with C APIs.
Vala's new can be a little weird when used as a parameter. I would recommend assigning the new list to a temporary, adding it to the list, then letting it go out of scope.
I would also recommend using libgee. It has better handling of generics than GLib.List and GLib.HashTable.

F# Referencing Types

I am working on a project where the F# code will be consumed by other .NET projects - so I am using classes. I created a code file like this:
namespace StockApplication
open System
type Stock =
{Symbol: String;
DayOpen: Decimal;
Price: Decimal;
}
member x.GetChange () =
x.Price - x.DayOpen
member x.GetPercentChange() =
Math.Round(x.GetChange()/x.DayOpen,4)
This works fine when I consume it from some unit tests written in C#. For example:
[TestMethod]
public void CreateStock_ReturnsValidInstance()
{
Stock stock = new Stock("TEST", 10, 10.25M);
Assert.IsNotNull(stock);
}
I then went to create another file with another class. This class uses the 1st class so I made sure it was below the original class in VS2012. When I created the next class, I can see it available via intellisense.
namespace StockApplication
open System
type StockTicker() =
member x.GetStock () =
StockApplication.Stock
However, every attept to either new it or refer it gives me the same error:
Error 1 The value, constructor, namespace or type 'Stock' is not
defined
Does anyone have any insight on why I can just simply new up a class that I created in F# in another F# file?
Thanks in advance.
Your C# test having Stock stock = new Stock("TEST", 10, 10.25M); that was compiled without a problem prompts to believe that F# constructor for the Stock should look the same. But this is not true and, perhaps, was the source of your confusion.
Your original
type Stock =
{Symbol: String;
DayOpen: Decimal;
Price: Decimal; }
is of F# type Record indeed, not an ordinary class. The following excerpt from MSDN applies:
Record construction also differs from class construction. In a record type, you cannot define a constructor.
Meaning that
let stock = Stock("ABC"; 10M; 10M)
will produce error FS0039: The value or constructor 'Stock' is not defined while
let stock = { Symbol = "ABC"; DayOpen = 10M; Price = 10M; }
will successfully create a record instance.
In order to build an instance of type Stock in your second F# type StockTicker you should use record construction syntax, something like
member x.GetStock () = { Symbol = "MSFT"; DayOpen = 32M; Price = 32.5M; }
which compiles without any problems.
When it comes to interop use of F# record from C# the latter follows the syntax that you applied in your test method.
OK, after digging into this reference (MSDN was 0 help) here, I found the answer.
Here is the syntax for the Stock class:
namespace StockApplication
open System
type Stock = class
val Symbol: String
val DayOpen: Decimal
val Price: Decimal
new (symbol, dayOpen, price) =
{
Symbol = symbol;
DayOpen = dayOpen;
Price = price
}
member x.GetChange () =
x.Price - x.DayOpen
member x.GetPercentChange() =
Math.Round(x.GetChange()/x.DayOpen,4)
end
And here is the syntax for the consuming class:
namespace StockApplication
type StockTicker() =
member x.GetStock () =
let y = new Stock("AET",1m,1m)
y.DayOpen

Modeling database records as types

I'm rewriting a C# library in F# in which most of the classes map one-to-one with database tables (similar to ActiveRecord). I'm considering whether to use records or classes (maybe even DUs?). There's a fair amount of validation in the property setters to maintain invariants. What would be the best way to model this in F#? I don't want an object that violates business logic to be persisted to the database. Any ideas are welcome.
A few additional thoughts...
Is it better to move the invariants to an external 'controller' class? Coming from C# it feels wrong to allow an object that corresponds to a database record to contain anything that can't be saved to the database. I suppose because failing earlier seems better than failing later.
You can have your data in a record, and still keep the validation logic with the data type, by attaching methods to the record:
type Person =
{ First : string;
Last : string; } with
member x.IsValid () =
let hasValue = System.String.IsNullOrEmpty >> not
hasValue x.First && hasValue x.Last
let jeff = { First = "Jeff"; Last = "Goldblum" }
let jerry = { jeff with First = "Jerry" }
let broken = { jerry with Last = "" }
let valid = [jeff; jerry; broken]
|> List.filter (fun x -> x.IsValid())
The copy semantics for records are almost as convenient as setting a property. The validation doesn't happen on property set, but it's easy to filter a list of records down to only the valid ones.
This should actually be a good way for you to handle it. Having your validation logic in the constructor will give you piece of mind later on in your code because the object is immutable. This also opens up multi-threading possibilities.
Immutable Version
type Customer (id, name) =
do // Constructor
if id <= 0 then
raise(new ArgumentException("Invalid ID.", "id"))
elif String.IsNullOrEmpty(name) then
raise(new ArgumentException("Invalid Name.", "name"))
member this.ID
with get() = id
member this.Name
with get() = name
member this.ModifyName value =
new Customer(id, value)
Mutable Version
type Customer (id) =
let mutable name = ""
do // Constructor
if id <= 0 then
raise(new ArgumentException("Invalid ID.", "id"))
member this.ID
with get() = id
member this.Name
with get() = name
and set value =
if String.IsNullOrEmpty(name) then
raise(new ArgumentException("Invalid Name.", "value"))
name <- value
Have you taken a look at my FunctionalNHibernate project? It's designed as a layer on top of nhibernate to let you declaratively map records to a database. It's early days, but it's just about usable:
http://bitbucket.org/robertpi/functionalnhibernate/

Resources