yylval and union - parsing

What is the purpose of union in the yacc file? Is it directly related to yylval in the flex file? If you don't use yylval, then you don't need to use union?

The purpose of the union is to allow storing different kind of objects into nodes emitted by flex.
To explain better you can have for example:
%union
{
int intValue;
float floatValue;
char *stringValue;
}
in .y if you want to provide basic support for int, float and string types. What can you do with this?
Two things:
First, you can automatically set right values when generating tokens. Think about .l file of the previous example, you can have:
[a-zA-Z][a-zA-Z0-9]* {
yylval.stringValue = strdup(yytext);
return IDENTIFIER;
}
[0-9]+ {
yylval.intValue = atoi(yytext);
return INTEGER;
}
[0-9]*\.[0-9]+"f"? {
yylval.floatValue = new atof(yytext);
return FLOAT;
}
In addition you can use value directly in your flex grammar:
nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }
Finally if you plan to use an OOP syntax tree you can define union as
%union
{
class ASTNode *node;
}
in which ASTNode is the ancestor class of any kind of syntax node.

The %union declaration modifies the type of yylval.
The bison manual explains:
In an ordinary (nonreentrant) parser, the semantic value of the token must be stored into the global variable yylval. When you are using just one data type for semantic values, yylval has that type. Thus, if the type is int (the default), you might write this in yylex:
...
yylval = value; /* Put value onto Bison stack. */
return INT; /* Return the type of the token. */
...
When you are using multiple data types, yylval's type is a union made from the %union declaration (see section The Collection of Value Types). So when you store a token's value, you must use the proper member of the union. If the %union declaration looks like this:
%union {
int intval;
double val;
symrec *tptr;
}
then the code in yylex might look like this:
...
yylval.intval = value; /* Put value onto Bison stack. */
return INT; /* Return the type of the token. */
...

Related

clang cast callExpr.getArg type to decl

i want to implement a interpreter based on Clang.i meet a problem. i creat a map to store vardecl and it corresponding int value. but when i visit callExpr,the function callExpr.getArg return type is expr,i want to cast it to decl type. how can i figure this problem?
example
int a = 10;
int main(){
PRINT(a) //self-define function
}
mymapdecl[a] = 10,but PRINTExpr.getArg type is expr.
I use dyn_cast<DeclRefExpr>(left)to get DeclRefExpr type,but it return null pointer.

How to return two specific types from a generic method?

T getValue<T>(int i) {
if (T == String) return '$i'; // Error
return i; // Error
}
void main() {
var s = getValue<String>(1);
var i = getValue<int>(1);
}
I want getValue to return string if T is String and int otherwise. How to do that?
You can't restrict the type parameter to just int or String, so it will have to accept more than that (at least their least common supertype, Object, so basically any type).
It's not a particularly helpful way to code. It's possible, but not recommended:
T getValue<T>(int i) {
if (i is T) return i;
return "$i" as T;
}
This will return the int if T allows it (so T being any of int, or a super type of int, which is num, Object, dynamic or void, or any number of Comparable<X> wrappings around any any of those supertypes), and otherwise try to return a string. That will fail with a type error unless T is String (since we've already ruled out all supertypes of String).
You can still call it as getValue<bool>(42) and watch it fail, so the type argument doesn't help with correctness.
It's not particularly effective. I'd rather do:
dynamic getValue(int i, {bool toString = false}) {
if (toString) return "$i";
return i;
}
and call it as:
String x = getValue(42, toString: true); // Add `as String` if you disable downcasts.
int y = getValue(42); // And `as int` here.
The type parameter is really just making things harder. You are going to cast or type-check the result anyway, so might as well do it at the call point, rather than introduce type variables that aren't actually preventing misuse anyway.
(I'd probably just do two different functions, but I assume that there is a reason for wanting one function).
As I mentioned in the comments, I don't see any way that you could use your generic as the return type of your getValue function. Even assuming the return under the if statement worked, there is nothing that can be done about trying to return int i when List is passed as the type. You'll be trying to return an int as a List.
If you change it to dynamic, your code will work fine as it's just using the generic as another parameter.
dynamic getValue<T>(int i) {
if (T == String) return '$i';
return i;
}
void main() {
var s = getValue<String>(1);
var i = getValue<int>(1);
}

File operation in drivers and struct declaration

i am trying to figure out how the code behind a basic kernel driver works.
I have the following struct:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
And my dev_open function is defined as:
static int dev_open(struct inode *, struct file *);
Now Im also familiar with the fact that the prototype for opening a device file is defined in the linux/fs.h:
http://lxr.linux.no/linux+v3.10/include/linux/fs.h#L1517
Here is the specific line from that link:
int (*open) (struct inode *, struct file *);
Now my question is what is the relationship between .open = dev_open, and int (*open) (struct inode *, struct file *);
which is defined in linux/fs.h? Is it passing the address of dev_open to the function pointer int (*open) defined in the linux/fs.h? There must be some relation or what is the point of defining the struct fops as type "file operation"?
A similar question was asked and answered here but i feel that my question was left out:
File operations in drivers
Thank you
I think this question is more about C than the Linux kernel.
Members of structure or union types cannot have function type, but they can have pointer to function type. For example, in the Linux kernel, the open member of struct file_operations needs to be declared with a pointer to function type: int (*open)(struct inode *, struct file *);. Declaring the member as int open(struct inode *, struct file *); is an error.
In this variable definition in Linux kernel code:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
Incidentally, the above should normally have the owner member initialized like so:
.owner = THIS_MODULE,
The expressions dev_open, dev_read, dev_write and dev_release are function designators being used as assignment expressions to initialize the members of fops. A function designator is an expression that has function type. Unless it is the operand of sizeof, _Alignof, or the unary & operator, a function designator is converted to a pointer to function type. Therefore, the above definition of variable foo is exactly equivalent to:
static struct file_operations fops =
{
.open = &dev_open,
.read = &dev_read,
.write = &dev_write,
.release = &dev_release,
};
(Don't forget to also initialize .owner = THIS_MODULE,.)
There, the function designators are operands of the unary & operator and so are not converted to pointer to function types implicitly, but the & operator is converting them to pointer to function types explicitly.
After the above initialization of fops, rc = fops.open(inode, file); indirectly calls dev_open(inode, file) and assigns the return value to rc. You may sometimes see this written in an older style: rc = (*fops.open)(inode, file);. They both do the same thing. The operand of the function call operator ( ) is in fact always a pointer to a function. In the case of rc = (*fops.open)(inode, file);, fops.open has a pointer to a function type. (*fops.open) dereferences fops.open to a function type but since (*fops.open) is a function designator it is implicitly converted back to a pointer to function type before the function call. Similarly, in the direct call rc = dev_open(inode, file);, dev_open is a function designator and so has a function type, but is implicitly converted to a pointer to function type before the function call.

Using an 'is' expression when the right-hand operand is a variable?

I am trying to write a function that takes two arguments: givenType and targetType. If these two arguments match, I want givenType to be returned, otherwise null.
For this objective, I am trying to utilize Dart's is expression (maybe there is a better way to go about it, I am open to suggestions). Initially, I thought it would be as simple as writing this:
matchesTarget(givenType, targetType) {
if (givenType is targetType) {
return givenType;
}
return null;
}
But this produces an error:
The name 'targetType' isn't a type and can't be used in an 'is'
expression. Try correcting the name to match an existing
type.dart(type_test_with_non_type)
I tried looking up what satisfies an is expression but cannot seem to find it in the documentation. It seems like it needs its right-hand operand to be known at compile-time (hoping this is wrong, but it does not seem like I can use a variable), but if so, how else can I achieve the desired effect?
I cant guess the purpose of the function (or the scenario where it would be used, so if you can clarify it would be great). First of all, I don't know if you are passing "types" as arguments. And yes, you need to specify in compile time the right hand argument of the is function.
Meanwhile, if you are passing types, with one change, you can check if the types passed to your function at runtime.
matchesTarget(Type givenType, Type targetType) {
print('${givenType.runtimeType} ${targetType.runtimeType}');
if (givenType == targetType) {
return givenType;
}
return null;
}
main(){
var a = int; //this is a Type
var b = String; //this is also a Type
print(matchesTarget(a,b)); //You are passing different Types, so it will return null
var c = int; //this is also a Type
print(matchesTarget(a,c)); //You are passing same Types, so it will return int
}
But if you are passing variables, the solution is pretty similar:
matchesTarget(givenVar, targetVar) {
print('${givenVar.runtimeType} ${targetVar.runtimeType}');
if (givenVar.runtimeType == targetVar.runtimeType) {
return givenVar.runtimeType;
}
return null;
}
main(){
var a = 10; //this is a variable (int)
var b = "hello"; //this is also a variable (String)
print(matchesTarget(a,b)); //this will return null
var c = 12; //this is also a variable (int)
print(matchesTarget(a,c)); //this will return int
}
The Final Answer
matchesTarget(givenVar, targetType) {
print('${givenVar.runtimeType} ${targetType}');
if (givenVar.runtimeType == targetType) {
return givenVar;
}
return null;
}
main(){
var a = 10; //this is a variable (int)
var b = String; //this is a type (String)
print(matchesTarget(a,b)); //this will return null because 'a' isnt a String
var c = int; //this is also a type (int)
print(matchesTarget(a,c)); //this will return the value of 'a' (10)
}
The as, is, and is! operators are handy for checking types at runtime.
The is operator in Dart can be only used for type checking and not checking if two values are equal.
The result of obj is T is true if obj implements the interface specified by T. For example, obj is Object is always true.
See the below code for an example of how to use the is operator
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
Even the error message that you're getting says that
The name 'targetType' isn't a type and can't be used in an 'is'
expression.
So the bottomline is that you can use is only for checking if a variable or value belongs to a particular data type.
For checking equality, you can use the == operator if comparing primitive types, or write your own method for comparing the values. Hope this helps!

How does F# know that bitArray elements are bool while enumerating in seq builder?

seq{
for bit in BitArray(10) do
yield bit
}
bit is of bool type. I checked with ILSpy and there's an explicit cast added in one of closures generated.
BitArray implements only plain (not generic) IEnumerable. How does F# know that it's a bool?
According to the F# 4.1 specification's Section 6.5.6 Sequence Iteration Expressions, F# does casting even for a non-generic IEnumerable if the IEnumerable has an Item property with a non-object type (highlighting mine):
An expression of the following form is a sequence iteration
expression:
for pat in expr1 do expr2 done
The type of pat is the same as the return type of the Current property on the enumerator value. However,
if the Current property has return type obj and the collection type ty
has an Item property with a more specific (non-object) return type
ty2, type ty2 is used instead, and a dynamic cast is inserted to
convert v.Current to ty2.
If we look at the source code for BitArray, we see that it does indeed have an Item property with type bool:
public bool this[int index] {
get {
return Get(index);
}
set {
Set(index,value);
}
}
Thus, F# will explicitly cast to bool while iterating.

Resources