I want to traverse the AST of a simple class having one member variable and one method. I have figured out that the class is represented as CXXRecordDecl.
What is the api within CXXREcordDecl to get the list of member variables which are represented as FieldDecl ?
The fields can be retrieved with RecordDecl::fields (there exist also methods the get the begin and end iterators of that range), e.g. for a CXXRecordDecl
CXXRecordDecl* cl = ...;
for (const auto& field : cl->fields) {
const auto& name = field->getName();
const auto field_cl = field->getType()->getAsCXXRecordDecl();
}
Similarly you would access the methods with methods().
Related
In Dart, what's the difference between List.from and List.of, and between Map.from and Map.of? Their documentation is not totally clear:
/**
* Creates a [LinkedHashMap] instance that contains all key/value pairs of
* [other].
*
* The keys must all be instances of [K] and the values of [V].
* The [other] map itself can have any type.
*
* A `LinkedHashMap` requires the keys to implement compatible
* `operator==` and `hashCode`, and it allows `null` as a key.
* It iterates in key insertion order.
*/
factory Map.from(Map other) = LinkedHashMap<K, V>.from;
/**
* Creates a [LinkedHashMap] with the same keys and values as [other].
*
* A `LinkedHashMap` requires the keys to implement compatible
* `operator==` and `hashCode`, and it allows `null` as a key.
* It iterates in key insertion order.
*/
factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
/**
* Creates a list containing all [elements].
*
* The [Iterator] of [elements] provides the order of the elements.
*
* All the [elements] should be instances of [E].
* The `elements` iterable itself may have any element type, so this
* constructor can be used to down-cast a `List`, for example as:
* ```dart
* List<SuperType> superList = ...;
* List<SubType> subList =
* new List<SubType>.from(superList.whereType<SubType>());
* ```
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
external factory List.from(Iterable elements, {bool growable: true});
/**
* Creates a list from [elements].
*
* The [Iterator] of [elements] provides the order of the elements.
*
* This constructor creates a growable list when [growable] is true;
* otherwise, it returns a fixed-length list.
*/
factory List.of(Iterable<E> elements, {bool growable: true}) =>
new List<E>.from(elements, growable: growable);
Is the difference related to generics? Maybe the .from factories let you change the type of the list, while the .of ones do not? I come from a Java background, which works with type erasure, and maybe types are reified in Dart and you cannot use casts or raw types to change list/map types?
The important difference between the from and of methods are that the latter have type annotations and the former do not. Since Dart generics are reified and Dart 2 is strongly typed, this is key to both ensuring the List/Map is correctly constructed:
List<String> foo = new List.from(<int>[1, 2, 3]); // okay until runtime.
List<String> bar = new List.of(<int>[1, 2, 3]); // analysis error
And ensuring that the types are inferred correctly:
var foo = new List.from(<int>[1, 2, 3]); // List<dynamic>
var bar = new List.of(<int>[1, 2, 3]); // List<int>
In Dart 1 types were completely optional, so many APIs were untyped or partially typed. List.from and Map.from are good examples, since the Iterable/Map passed into them doesn't have a type parameter. Sometimes Dart can figure out what the type of this object should be, but sometimes it just ended up as List<dynamic> or Map<dynamic, dynamic>.
In Dart 2 the type dynamic was changed from being both a top (Object) and bottom (null) type to only being a top type. Thus if you created a List<dynamic> accidentally in Dart 1 you could still pass it to a method which required a List<String>. But in Dart 2 List<dynamic> is almost the same as List<Object>, so this would fail.
If you are using Dart 2, you should always use the typed version of these APIs. Why do the old ones still exist, and what are the plans there? I don't really know. I would guess they would be phased out over time, along with the rest of the Dart 1.
Whenever possible it is better to use collection literals now rather than the .from or .of constructors. Apparently there are some performance benefits to this. (See link at bottom.)
Examples:
something.toList()
[...something]
Exception:
Can use .from if you need to downcast.
If you do use them, though, you should always include the type.
Source: Dart team engineer's post
List.of() and toList()
They are used to create a new list of the same type as the original, but List.of() can be used to upcast:
var ints = <int> [0];
var newList1 = ints.toList(); // List<int>
var newList2 = List<num>.of(ints); // List<num>
You can also copy a list by doing:
var newList3 = [...ints]; // List<int>
var newList4 = [for (var v in ints) v]; // List<int>
List.from()
Use this if you want to downcast and therefore it is important that the subtype is a type of supertype.
var ints = List<int>.from(<num>[0, 1]); // Good as all elements are of type `int`
var ints = List<int>.from(<num>[0, 1.5]); // Bad as some elements are of type `double`
I am writing unit tests to exercise various code paths involving a factory class.
The factory returns a std::unique_ptr to a base type:
class Base {};
class Derived1 : public class Base {};
class Derived2 : public class Base {};
std::unique_ptr<Base> Type::Factory(enum rtype) const {
switch(rtype) {
case d1: return std::make_unique<Derived1>();
case d2: return std::make_unique<Derived2>();
default: return std::make_unique<Derived1>();
}
}
So in the test I want to ensure that the correct type is returned (factories are breeding ground for cut'n'paste bugs).
Is there a way of checking what type is returned?
This: EXPECT_TRUE(typeid(Derived1), typeid(type.get()); is false because the type.get() is that of Base and not the rtype that was passed in.
This: EXPECT_TRUE(typeid(Derived1), typeid(type.get()); is false because the type.get() is that of Base and not the rtype that was passed in.
typeid( type.get() ) will get the typeid of the base pointer, i.e. the type that get() is declared as returning. To get the real dynamic type of the pointed-to object, whatever that may be, you should dereference the pointer:
typeid( *type.get() )
You need to use RTTI. The type is erased to Base when used.
You can do a dynamic cast to get the proper type, something like:
EXPECT_FALSE(dynamic_cast<Derived1*>(type.get()) == nullptr)
If dynamic_cast fails (type is not of Derived1) dynamic_cast will return a nullptr.
I'm new to Dart and tried to get a class to implement List using the answers here, and tried to sort a list of these objects using the docs here. I deleted most of my code in an effort to post a MWE:
import 'dart:collection';
class Transaction<E> extends ListBase<E>{
DateTime when;
Transaction(this.when);
List innerList = new List();
int get length => innerList.length;
void set length(int length){
innerList.length = length;
}
void operator[]=(int index, E value){
innerList[index] = value;
}
E operator [](int index) => innerList[index];
void add(E value) => innerList.add(value);
void addAll(Iterable<E> all) => innerList.addAll(all);
}
class Forecaster{
var transactions;
Forecaster(){
this.transactions = new List<dynamic>();
}
void tabulate(){
transactions.sort((a,b) => a.when.compareTo(b.when)); //problem line?
for(var d in transactions){
d.asMap().forEach((index,content){
int len = content.toStringAsFixed(2).length;
});
}
}
void forecast(var forWhen){
var first = new Transaction(DateTime.now());
first.addAll([5,9]);
transactions.add(first);
}
}
void main(){
Forecaster myTest = new Forecaster();
var dub = myTest;
dub..forecast(DateTime.now())
..tabulate();
}
Running with the problem line results in an exception (Uncaught exception: TypeError: Closure 'Forecaster_tabulate_closure': type '(dynamic, dynamic) => dynamic' is not a subtype of type '(dynamic, dynamic) => int') I don't understand. If I comment out the problem line, the TypeError goes away. Is the TypeError because I did something wrong when defining Transaction? I'm attempting this with DartPad.
I'm new to Dart too, so my explanation might not be 100% on the money, but I believe, yes, the main issue is the type assignment of transactions. I think because you initialize it as a var, it is having trouble deducing the type of a.when, which is means it also doesn't know the type of a.when.compareTo(), and assumes dynamic. You are feeding the output of compareTo into List.sort() which is expecting an int from the anonymous function. Thus the error that it wanted an int but got dynamic.
The easiest way to address this is to initialize transactions with a more explicit type rather than as var:
List<Transaction> transactions;
Forecaster(){
this.transactions = new List<Transaction>();
}
Also, to confirm that it is an issue with it not being able to infer the return type of compareTo, I tried leaving your code as-is, but explicitly casting the result as int, and that also worked:
transactions.sort((a,b){
return (a.when.compareTo(b.when) as int);
});
Note: code like the above and using lots of dynamics and vars is in general not great practice with Dart - you lose a lot of the benefits of having a typed language. You might also notice that when you type in an IDE, you don't get methods auto-suggested when you do stuff like this - for example, until I changed transactions to an explicit type of list, typing a.when did not trigger autocomplete, and my IDE thought the type was dynamic, not DateTime.
Your problem is with the types. The code:
var transactions;
Forecaster(){
this.transactions = new List<dynamic>();
}
void tabulate(){
transactions.sort((a,b) => a.when.compareTo(b.when));
first declares transactions to have type dynamic.
Then you call sort on that with an argument which is inferred to have type dynamic Function(dynamic, dynamic) (because there is no clue available to say otherwise in the type of transactions).
However, the actual run-time type of transactions is List<Transaction>, and that requires a function argument of type int Function(Transaction, Transaction). The type dynamic Function(dynamic, dynamic) is not a sub-type of int Function(Transaction, Transaction) (the return type has to be a subtype of int for that to be the case) so you get a run-time error.
If you change transactions to have type List<Transaction>, then the type inference will have a clue when it gets to the function literal. It will infer that (a, b) => a.when.compareTo(b.when) in a context expecting int Function(Transaction, Transaction) will have that type.
Even if you just change transactions to List<dynamic>, it will still work, it will just make a.when.compareTo(b.when) be dynamic invocations.
This question already has answers here:
How do I translate a C union into Delphi?
(2 answers)
Closed 7 years ago.
I am attempting to interface with an embedded system that transmits and receives data with a fairly simple format but has strict sizing requirements.
In C, you would use a union type to expose some variable data with potentially different types located at the same spot in memory. Add a variable of this union type to a struct, and then you can (carefully) refer to that struct field with various names and types:
for simplicity, please ignore byte alignment and packing
typedef enum { F1_V1, F1_V2, F1_V3 } FLAG_1_T;
typedef enum { F2_V1, F2_V1 } FLAG_2_T;
typedef union
{
FLAG_1_T flag_1;
FLAG_2_T flag_2;
}
FLAG_T;
typedef struct
{
BYTE_T id;
INT32_T value;
FLAG_T flag;
}
DATA_ITEM_T;
So now I can interpret the flag field as either FLAG_1_T or FLAG_2_T.
I would like to use this same sort of approach in Delphi 2010. I've tried to accomplish this by using absolute addressing for fields of a record:
type
FLAG_1_T = ( F1_V1, F1_V2, F1_V3 );
FLAG_2_T = ( F1_V1, F1_V2 );
type
DATA_ITEM_T = record
id : BYTE_T;
value : INT32_T;
flag_1 : FLAG_1_T;
flag_2 : FLAG_2_T absolute flag_1;
end;
But this fails to compile with syntax error E2029 ';' expected but identifier 'absolute' found.
If I bring those flag declarations outside of the record type definition (but at the same scope as the record type def), it compiles fine:
note that this is useless for what I'm trying to accomplish
type
FLAG_1_T = ( F1_V1, F1_V2, F1_V3 );
FLAG_2_T = ( F1_V1, F1_V2 );
type
DATA_ITEM_T = record
id : BYTE_T;
value : INT32_T;
end;
var
flag_1 : FLAG_1_T;
flag_2 : FLAG_2_T absolute flag_1;
So why can't I do this within a record? Is there another way to accomplish this?
You can translate a C union to Delphi using a record type with a variant part:
type
FLAG_T = record
case Boolean of
False: (flag_1: FLAG_1_T);
True: (flag_2: FLAG_2_T);
end;
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