Dissecting a complex type in C++ using the clang/llvm AST api - llvm-clang

Let's say I have a program with the following declaration:
std::vector<std::vector<std::vector<std::string> *> > s;
Now I would like to tokenize this, cut it in parts:
std vector
std vector
std vector pointer
std string
When going through the source-code, this example will give me a VarDecl. If I understood it correctly, this VarDecl contains the whole declaration. Now I think the next step is invoking getType() on that VarDecl. But then what? I expected a method that would return e.g. an iterator or so.
Below you'll see what I have. This works fine for e.g. "int i" or "const char *const i = NULL;" even for "const std::string l = "12";" but "std::vector *> > s;" results in an "int"?(!?).
void dissectType(ASTContext *const Context, const QualType x)
{
if (x.isNull())
return;
QualType type = x.getNonReferenceType();
for(;!type.isNull();) {
if (type.hasQualifiers()) {
Qualifiers q = type.getQualifiers();
if (q.hasConst())
printf("const ");
if (q.hasVolatile())
printf("volatile ");
if (q.hasRestrict())
printf("restrict ");
}
const Type *t = type.getTypePtr();
if (!t) {
printf("null?\n");
break;
}
else if (t -> isPointerType())
printf("* ");
else if (t -> isFundamentalType()) {
std::string curType = type.getUnqualifiedType().getAsString();
printf("%s\n", curType.c_str());
break; // should be last entry in this chain
}
type = type->getPointeeType();
}
}

Related

How do I write a function that returns itself?

What I want to make is a function, that returns itself, so I can call it like this:
foo()()...()
In C# it would be done via delegates:
delegate SelfFunc SelfFunc();
static void Main() {
SelfFunc foo = null;
foo = () => {
return foo;
};
foo()()...();
}
Anticipating questions like "why implement such silly behavior?": I want to sum numbers in a very strange way using single function continues calls: foo(1)(2)(3)() = 6, but in this question I just want to know how to return function itself. Example realization of this method that I made in C#. This is all just for fun and to learn Rust:
static int sum = 0;
delegate dynamic InfFunc(int i = int.MaxValue);
static void InfFuncTest() {
InfFunc f = null;
f = (int i) => {
if(i == int.MaxValue) {
return sum;
}
sum += i;
return f;
};
var g = f;
var value = g(1)(2)(3)();
Console.WriteLine(value);
}
A function that returns itself is possible on nightly.
First you need to enable the features unboxed_closures and fn_traits.
Then you can define a struct which, when called, returns self. The full code looks something like this:
#![feature(unboxed_closures, fn_traits)]
struct SelfFunc;
impl FnOnce<()> for SelfFunc {
type Output = SelfFunc;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self
}
}
Then you can call the function as many times as you want:
fn main() {
let f = SelfFunc;
f()()()()()();
}
Based on #cameron1024's answer, you can "overload" using traits, but you will need 2 structs to handle the empty case properly of foo() (here called Add) without any arguments returning 0.
#![feature(unboxed_closures, fn_traits)]
struct Add;
impl FnOnce<(u32,)> for Add {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
AddImpl(args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
0
}
}
struct AddImpl(u32);
impl FnOnce<()> for AddImpl {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
impl FnOnce<(u32,)> for AddImpl {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Self(self.0 + args.0)
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
dbg!( Add() );
}
Playground
If you do not care about the no-args foo() requirement, you can make Add a tuple struct instead and remove AddImpl:
#![feature(unboxed_closures, fn_traits)]
struct Add(u32);
impl FnOnce<(u32,)> for Add {
type Output = Add;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Add(self.0 + args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
//dbg!( Add() ); // doesn't compile
}
Playground
Although I should note that this likely isn't such a great idea, using an slice/iterator would likely result in cleaner code:
fn main() {
dbg!([1, 2, 3].iter().copied().sum::<u32>());
}
Playground

Absolute value function in Rust

In this elementary Rust program a function calculates the absolute value of an integer, and main() helps in completing a statement with the result:
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
print!("The abs value of {} is ", x);
if x > 0 {
return x;
} else {
-x
}
}
Is there a way to print correctly the whole statement "The abs value of... is..." into the abs() function? I tried unsuccessfully with
println!("The abs value of {} is {} ", x, x);
This always prints the value of the x parameter (e.g. -4, -4) so it's not correct.
And with
println!("The abs value of {} is {} ", x, abs(x));
But here, for some reason, Rust is not happy with recursion, gives a warning at compilation and then doesn't run the program.
The absolute value method is already defined; you do not need to implement it yourself
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
let val = x.abs();
println!("The abs value of {} is {}", x, val);
val
}
Try this to avoid recursion:
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
let y = if x >= 0 { x } else { -x };
println!("The abs value of {} is {} ", x, y);
y
}
Output:
The abs value of -4 is 4
4.
There are built-in .abs() method for primitive types e.g.
i8,
i16,
i32,
i64,
i128,
f32,
and f64:
assert_eq!(10i32.abs(), 10);
assert_eq!((-10i32).abs(), 10);
Overflow behavior
The absolute value of i32::min_value() cannot be represented as an
i32, and attempting to calculate it will cause an overflow. This
means that code in debug mode will trigger a panic on this case and
optimized code will return i32::min_value() without a panic.
The following code, will panic in debug mode (and returns -128 in release mode):
fn main() {
let a = -128_i8;
println!("{}", a); // -128
let b = a.abs();
println!("{}", b); // -128
}
Since abs(-2_147_483_648_i32) is 2_147_483_648_u32, you may return u32 instead of i32:
fn abs(x: i32) -> u32 {
if x >= 0 {
x as u32
} else if x == std::i32::MIN {
2_147_483_648_u32
} else {
-x as u32
}
}
fn main() {
let value = abs(std::i32::MIN); // i32::min_value() // -2_147_483_648i32
println!("{}.", value); // 2147483648
}
Output:
2147483648

How to pass a function as argument in Rust

Given the following rust program:
fn call_twice<A>(val: A, f: fn(A) -> A) -> A {
f(f(val))
}
fn main() {
fn double(x: int) -> int {x + x};
println!("Res is {}", call_twice(10i, double));
// println!("Res is {}", call_twice(10i, (x: int) -> int {x + x}));
// ^ this line will fail
}
Why can I pass double as the function, but not inlined? What is a good way to achieve the same behaviour without defining the function somewhere?
2016-04-01 Update:
As of Rust 1.0, the code should look like this:
fn call_twice<A, F>(val: A, mut f: F) -> A
where F: FnMut(A) -> A {
let tmp = f(val);
f(tmp)
}
fn main() {
fn double(x: i32) -> i32 {x + x};
println!("Res is {}", call_twice(10, double));
println!("Res is {}", call_twice(10, |x| x + x));
}
The change to the closure parameter is because closure are now unboxed.
Original:
Insofar as I know, you can't define functions inline like that.
What you want is a closure. The following works:
fn call_twice<A>(val: A, f: |A| -> A) -> A {
let tmp = f(val);
f(tmp)
}
fn main() {
fn double(x: int) -> int {x + x};
println!("Res is {}", call_twice(10i, double));
println!("Res is {}", call_twice(10i, |x| x + x));
}
There are a few things to note:
Functions coerce to closures, but the opposite isn't true.
You need to store the result of f(val) in a temporary due to borrowing rules. Short version: you need unique access to a closure to call it, and the borrow checker isn't quite clever enough to realise the two calls are independent in their original positions.
Closures are in the process of being replaced by unboxed closures, so this will change in the future, but we're not quite there yet.

json_spirit usage issue

i was able to compile the program successfully but not able to retrieve the values from json object. i am pasting the code below , the code is simple , any help appreciated.
#include <cstdio>
#include <cstring>
#include <json_spirit.h>
using namespace std;
using namespace json_spirit;
//A sample get file request
char *jsonInput =
"{\"request\" : { \
\"service\" : \"fmgr\" \
\"cookie\" : \"Abxruyyeziyrolsu\" \
\"req\" : \"read\" \
\"fname\" : \"Junk.txt\" \
\"size\" : 1024 \
\"data\" : \"data\" \
}}";
int main(int argc, char **argv)
{
Value val;
const string s = jsonInput;
read(s, val); //read the jsonInput to the value
Object obj = val.get_obj();
std::string service, cookie, req, fname, data;
uint32_t size;
for(Object::size_type i = 0; i != obj.size(); ++i) {
const Pair& pair = obj[i];
const string& name = pair.name_;
const Value& value = pair.value_;
if( name == "service" ) service = value.get_str();
else if( name == "cookie") cookie = value.get_str();
else if( name == "req" ) req = value.get_str();
else if( name == "fname" ) fname = value.get_str();
else if( name == "size" ) size = value.get_int();
else if( name == "data" ) data = value.get_str();
}
std::cout<<service << " " << cookie << " " << req << " " << fname << " " << size << " " << data ;
return 0;
}
There are two things problems:
The jsonInput string is not valid JSON, the commas to separate object pairs are missing.
The next issue is more complicated to explain. The toplevel Value is itself an Object so calling val.get_obj() returns the Object containing all the data. There is only one Pair in this object, named "request". Calling val.get_obj()[0] will retrieve this pair. You then need to get the Object out of this Pair's Value.
Value val; read(s, val); //read the jsonInput to the value
const Pair& pair = val.get_obj()[0]; //gets the name:value pair, named "request"
const Object& obj = pair.value_.get_obj(); //gets the service, cookie... object
To keep things simple, as they should be with json_spirit, try the following after correcting the missing ',' delimiters in the JSON string.
std::string json_input = <your valid JSON string>
json_spirit::Value value;
auto success = json_spirit::read_string(json_input, value);
if (success == true) {
auto object = value.get_obj();
for (auto entry : object) {
if (entry.name_ == "service") service = entry.value_.get_str();
else if...
.
.
}
}

Haskell: Dealing With Types And Exceptions

I'd like to know the "Haskell way" to catch and handle exceptions. As shown below, I understand the basic syntax, but I'm not sure how to deal with the type system in this situation.
The below code attempts to return the value of the requested environment variable. Obviously if that variable isn't there I want to catch the exception and return Nothing.
getEnvVar x = do {
var <- getEnv x;
Just var;
} `catch` \ex -> do {
Nothing
}
Here is the error:
Couldn't match expected type `IO a'
against inferred type `Maybe String'
In the expression: Just var
In the first argument of `catch', namely
`do { var <- getEnv x;
Just var }'
In the expression:
do { var <- getEnv x;
Just var }
`catch`
\ ex -> do { Nothing }
I could return string values:
getEnvVar x = do {
var <- getEnv x;
return var;
} `catch` \ex -> do {
""
}
however, this doesn't feel like the Haskell way. What is the Haskell way?
Edit: Updated code to properly reflect description.
You cannot strip away the IO and return Maybe String within a do-block. You need to return an IO (Maybe String).
getEnvVar x = do {
var <- getEnv x;
return (Just var);
} `catch` \ex -> do {
return Nothing
}
Why not use
import qualified System.IO.Error as E
getEnvVar :: String -> IO (Either IOError String)
getEnvVar = E.try . getEnv
Instead of Nothing and Just var, you get Left error and Right var.
Once you get that anything involving getEnv is going to involve returning a result in the IO monad, then there is nothing wrong with your basic approach. And while you could use System.IO.Error (and I would), it is just as valid, and instructive, to write it the way you did. However, you did use a bit more punctuation than idomatic Haskell would use:
getEnvVar x = (Just `fmap` getEnv x) `catch` const (return Nothing)
or
getEnvVar x = getEnv x `catch` const (return "")
You could also try
import System.Environment
getEnvVar :: String -> IO (Maybe String)
getEnvVar x = getEnvironment >>= return . lookup x
or a bit longer, but maybe easier to follow:
getEnvVar x = do
fullEnvironment <- getEnvironment
return (lookup x fullEnvironment)
if you don't mind going through the whole environment the whole time.