Skip to content

Commit

Permalink
Typedef for union. Fixes #475, #496, #508, #522, #524 and #556 (#523)
Browse files Browse the repository at this point in the history
  • Loading branch information
Konstantin8105 authored and elliotchance committed Jan 14, 2018
1 parent c7c0eba commit 7b46c33
Show file tree
Hide file tree
Showing 12 changed files with 463 additions and 303 deletions.
13 changes: 12 additions & 1 deletion tests/enum.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
#include <stdio.h>
#include "tests.h"

/* Text */
enum number{zero, one, two, three};

/**
* Text
*/
enum
{
_ISupper = ((0) < 8 ? ((1 << (0)) << 8) : ((1 << (0)) >> 8)),
_ISalnum = ((11) < 8 ? ((1 << (11)) << 8) : ((1 << (11)) >> 8))
};

/** <b> Text </b> */
enum year{Jan, Feb, Mar, Apr, May, Jun, Jul,
Aug, Sep, Oct, Nov, Dec};

// Text
enum State {Working = 1, Failed = 0, Freezed = 0};

// Text
// Text
enum day {sunday = 1, monday, tuesday = 5,
wednesday, thursday = 10, friday, saturday};

Expand All @@ -22,12 +30,15 @@ enum state currState = 2;
enum state FindState() {return currState;}

enum { FLY , JUMP };
// TYPEDEF

/// TYPEDEF
typedef enum {
a, b, c
} T_ENUM;

/**
* Text
*/
typedef enum e_strategy {RANDOM, IMMEDIATE = 5, SEARCH} strategy;

// main function
Expand Down
62 changes: 61 additions & 1 deletion tests/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,27 @@ void pass_by_val(struct programming value)
is_streq(value.pointer, "Programming in Software Development.");
}

/**
* text
*/
typedef struct mainStruct{
double constant;
} secondStruct;

/*
* Text
*/
typedef struct {
double t;
} ts_c;

// Text
typedef struct ff {
int v1,v2;
} tt1, tt2;

// Text1
// Text2
struct outer {
int i;
struct z {
Expand All @@ -50,6 +59,9 @@ struct outer {

struct xx {
int i;
/**
* Text
*/
struct yy {
int j;
struct zz {
Expand All @@ -58,13 +70,41 @@ struct xx {
} inner;
};

/**
* Some function
*/
int summator(int i, float f){
return i+(int)(f);
}

typedef struct J J;
struct J
{
float f;
int (*fu)(J *j, float i);
};

int j_function(J *j, float i)
{
if (j != NULL)
{
return (int)(i+(*j).f);
}
return -1;
};

void struct_with_rec_fuction()
{
J j;
j.f = 5.0;
j.fu = j_function;
is_eq(j.fu(&j,4.0),9);
is_eq(j_function(NULL, 4.0),-1);
}

int main()
{
plan(44);
plan(48);

struct programming variable;
char *s = "Programming in Software Development.";
Expand Down Expand Up @@ -229,6 +269,24 @@ int main()
is_eq(f(3,5),8);
}

diag("typedef struct C C inside function")
{
typedef struct CCC CCC;
struct CCC {
float ff;
};
CCC c;
c.ff = 3.14;
is_eq(c.ff,3.14);
}
typedef struct CP CP;
struct CP {
float ff;
};
CP cp;
cp.ff = 3.14;
is_eq(cp.ff,3.14);

diag("struct name from Go keyword")
{ struct chan {int i;}; struct chan UU; UU.i = 5; is_eq(UU.i,5);}
{ struct defer {int i;}; struct defer UU; UU.i = 5; is_eq(UU.i,5);}
Expand Down Expand Up @@ -267,5 +325,7 @@ int main()
{ typedef struct {int i;} init ; init UU; UU.i = 5; is_eq(UU.i,5);}
*/

struct_with_rec_fuction();

done_testing();
}
113 changes: 112 additions & 1 deletion tests/union.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,116 @@ void union_inside_struct()
is_eq(sha2.ff2 , 12.444);
}

typedef union myunion myunion;
typedef union myunion
{
double PI;
int B;
}MYUNION;

typedef union
{
double PI;
int B;
}MYUNION2;

void union_typedef()
{
diag("Typedef union")
union myunion m;
double v = 3.14;
m.PI = v;
is_eq(m.PI,3.14);
is_true(m.B != 0);
is_eq(v, 3.14);
v += 1.0;
is_eq(v, 4.14);
is_eq(m.PI,3.14);

MYUNION mm;
mm.PI = 3.14;
is_eq(mm.PI,3.14);
is_true(mm.B != 0);

myunion mmm;
mmm.PI = 3.14;
is_eq(mmm.PI,3.14);
is_true(mmm.B != 0);

MYUNION2 mmmm;
mmmm.PI = 3.14;
is_eq(mmmm.PI,3.14);
is_true(mmmm.B != 0);
}

typedef struct FuncDestructor FuncDestructor;
struct FuncDestructor {
int i;
};
typedef struct FuncDef FuncDef;
struct FuncDef {
int i;
union {
FuncDef *pHash;
FuncDestructor *pDestructor;
} u;
};

void union_inside_struct2()
{
FuncDef f;
FuncDestructor fd;
fd.i = 100;
f.u.pDestructor = &fd;

FuncDestructor * p_fd = f.u.pDestructor;
is_eq((*p_fd).i , 100);

is_true(f.u.pHash != NULL);
is_true(f.u.pDestructor != NULL);
int vHash = (*f.u.pHash).i;
is_eq(vHash , 100);
is_eq((*f.u.pHash).i , 100);
}

union UPNT{
int * a;
int * b;
int * c;
};

void union_pointers()
{
union UPNT u;
int v = 32;
u.a = &v;
is_eq(*u.a,32);
is_eq(*u.b,32);
is_eq(*u.c,32);
pass("ok")
}

union UPNTF{
int (*f1)(int);
int (*f2)(int);
};

int union_function(int a)
{
return a+1;
}

void union_func_pointers()
{
union UPNTF u;
u.f1 = union_function;
is_eq(u.f1(21), 22);
is_eq(u.f2(21), 22);
}

int main()
{
plan(11);
plan(33);

union programming variable;

Expand All @@ -89,6 +196,10 @@ int main()
pass_by_ref(&variable);

union_inside_struct();
union_typedef();
union_inside_struct2();
union_pointers();
union_func_pointers();

done_testing();
}
36 changes: 31 additions & 5 deletions transpiler/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ func transpileBinaryOperatorComma(n *ast.BinaryOperator, p *program.Program) (
return right[len(right)-1], preStmts, nil
}

func findUnion(node ast.Node) (unionNode ast.Node, haveMemberExprWithUnion bool) {
switch chi := node.(type) {
case *ast.MemberExpr:
if strings.HasPrefix(chi.Type, "union ") {
haveMemberExprWithUnion = true
unionNode = node
return
}
return findUnion(node.Children()[0])
case *ast.DeclRefExpr:
if strings.HasPrefix(chi.Type, "union ") {
haveMemberExprWithUnion = true
unionNode = node
return
}
}
return nil, false
}

func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsStmt bool) (
_ goast.Expr, resultType string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) {
defer func() {
Expand Down Expand Up @@ -271,11 +290,16 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
right = util.NewNil()
}

unionNode, haveMemberExprWithUnion := findUnion(n.Children()[0])

// Construct code for assigning value to an union field
if memberExpr, ok := n.Children()[0].(*ast.MemberExpr); ok {
ref := memberExpr.GetDeclRefExpr()
if ref != nil {
union := p.GetStruct(ref.Type)
if union == nil {
union = p.GetStruct("union " + ref.Type)
}
if union != nil && union.IsUnion {
attrType, err := types.ResolveType(p, ref.Type)
if err != nil {
Expand All @@ -296,11 +320,7 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
union := p.GetStruct(un.Type)
if union != nil && union.IsUnion {
if str, ok := un.Children()[0].(*ast.DeclRefExpr); ok {
attrType, err := types.ResolveType(p, memberExpr.Type)
if err != nil {
p.AddMessage(p.GenerateWarningMessage(err, memberExpr))
}
funcName := getFunctionNameForUnionSetter("", attrType, memberExpr.Name)
funcName := getFunctionNameForUnionSetter("", memberExpr.Type, memberExpr.Name)
funcName = str.Name + "." + un.Name + funcName
resExpr := &goast.CallExpr{
Fun: goast.NewIdent(funcName),
Expand All @@ -312,6 +332,12 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
}
}
}

// struct inside union
if haveMemberExprWithUnion {
p.AddMessage(p.GenerateWarningMessage(
fmt.Errorf("Binary operation with union not support. AST node with union : %v", unionNode), n))
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions transpiler/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func getName(firstChild ast.Node) string {
case *ast.MemberExpr:
if types.IsFunction(fc.Type) {
if decl, ok := fc.Children()[0].(*ast.DeclRefExpr); ok {
if strings.Contains(decl.Type, "union ") {
return getFunctionNameForUnionGetter(decl.Name, "", fc.Name) + "()"
}
return decl.Name + "." + fc.Name
}
}
Expand Down
Loading

0 comments on commit 7b46c33

Please sign in to comment.