Repository: Konstantin8105/c4go
Pull request #494 (2021-04-22 07:48:02)

Code quality

codecov[bot]: # [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) Report
> Merging [#494](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) (0fcb8b3) into [master](https://codecov.io/gh/Konstantin8105/c4go/commit/1043335a436e187bd94c8e119e62f6ddc9b1fd72?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) (1043335) will **increase** coverage by `0.07%`.
> The diff coverage is `72.72%`.

[![Impacted file tree graph](https://codecov.io/gh/Konstantin8105/c4go/pull/494/graphs/tree.svg?width=650&height=150&src=pr&token=esH2rHXlZ2&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)

```diff
@@            Coverage Diff             @@
##           master     #494      +/-   ##
==========================================
+ Coverage   82.75%   82.82%   +0.07%     
==========================================
  Files         193      193              
  Lines       10861    10861              
==========================================
+ Hits         8988     8996       +8     
+ Misses       1362     1354       -8     
  Partials      511      511              
```


| [Impacted Files](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) | Coverage Δ | |
|---|---|---|
| [transpiler/transpiler.go](https://codecov.io/gh/Konstantin8105/c4go/pull/494/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin#diff-dHJhbnNwaWxlci90cmFuc3BpbGVyLmdv) | `85.60% <72.72%> (+1.98%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin). Last update [1043335...0fcb8b3](https://codecov.io/gh/Konstantin8105/c4go/pull/494?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin).


Patch:
diff --git a/transpiler/branch.go b/transpiler/branch.go
index 048ee10..9af7754 100644
--- a/transpiler/branch.go
+++ b/transpiler/branch.go
@@ -190,7 +190,7 @@ func transpileForStmt(n *ast.ForStmt, p *program.Program) (
 					err)
 				return nil, nil, nil, err
 			}
-			preStmts = append(preStmts, combineStmts(before, newPre, newPost)...)
+			preStmts = append(preStmts, combineStmts(newPre, before, newPost)...)
 			children[0] = c.Children()[1]
 		}
 	case *ast.DeclStmt:
@@ -402,7 +402,7 @@ func transpileForStmt(n *ast.ForStmt, p *program.Program) (
 		Post: post,
 		Body: body,
 	}
-	block.List = combineStmts(&forStmt, preStmts, postStmts)
+	block.List = combineStmts(preStmts, &forStmt, postStmts)
 	block.Lbrace = 1
 
 	return &block, nil, nil, nil
diff --git a/transpiler/goto.go b/transpiler/goto.go
index 966bebf..20bcd6e 100644
--- a/transpiler/goto.go
+++ b/transpiler/goto.go
@@ -20,7 +20,7 @@ func transpileLabelStmt(n *ast.LabelStmt, p *program.Program) (*goast.LabeledStm
 		if err != nil {
 			return nil, nil, nil, err
 		}
-		post = combineStmts(stmt, preStmts, postStmts)
+		post = combineStmts(preStmts, stmt, postStmts)
 	}
 
 	return &goast.LabeledStmt{
diff --git a/transpiler/operators.go b/transpiler/operators.go
index 517999b..b9f197e 100644
--- a/transpiler/operators.go
+++ b/transpiler/operators.go
@@ -958,7 +958,7 @@ func atomicOperation(n ast.Node, p *program.Program) (
 				return
 			}
 
-			inBody := combineStmts(&goast.ExprStmt{X: expr}, preStmts, postStmts)
+			inBody := combineStmts(preStmts, &goast.ExprStmt{X: expr}, postStmts)
 
 			expr, exprType, preStmts, postStmts, err = atomicOperation(v.Children()[1], p)
 			if err != nil {
@@ -1040,7 +1040,7 @@ func atomicOperation(n ast.Node, p *program.Program) (
 			}
 
 			e, _, newPre, newPost, _ := transpileToExpr(v, p, false)
-			body := combineStmts(&goast.ExprStmt{X: e}, newPre, newPost)
+			body := combineStmts(newPre, &goast.ExprStmt{X: e}, newPost)
 
 			preStmts = nil
 			postStmts = nil
diff --git a/transpiler/transpiler.go b/transpiler/transpiler.go
index 90276e4..acb9082 100644
--- a/transpiler/transpiler.go
+++ b/transpiler/transpiler.go
@@ -302,35 +302,19 @@ func transpileToStmts(node ast.Node, p *program.Program) (
 	stmts []goast.Stmt, err error) {
 
 	if node == nil {
-		return nil, nil
-	}
-	defer func() {
-		stmts = nilFilterStmts(stmts)
-	}()
-
-	switch n := node.(type) {
-	case *ast.DeclStmt:
-		stmts, err = transpileDeclStmt(n, p)
-		if err != nil {
-			p.AddMessage(p.GenerateWarningMessage(
-				fmt.Errorf("error in DeclStmt: %v", err), n))
-			err = nil // Error is ignored
-		}
 		return
 	}
 
-	var (
-		stmt      goast.Stmt
-		preStmts  []goast.Stmt
-		postStmts []goast.Stmt
-	)
-	stmt, preStmts, postStmts, err = transpileToStmt(node, p)
+	stmt, preStmts, postStmts, err := transpileToStmt(node, p)
 	if err != nil {
 		p.AddMessage(p.GenerateWarningMessage(
 			fmt.Errorf("error in DeclStmt: %v", err), node))
 		err = nil // Error is ignored
 	}
-	return combineStmts(stmt, preStmts, postStmts), err
+
+	stmts = combineStmts(preStmts, stmt, postStmts)
+	stmts = nilFilterStmts(stmts)
+	return
 }
 
 func transpileToStmt(node ast.Node, p *program.Program) (
@@ -436,11 +420,19 @@ func transpileToStmt(node ast.Node, p *program.Program) (
 		var stmts []goast.Stmt
 		stmts, err = transpileDeclStmt(n, p)
 		if err != nil {
+			p.AddMessage(p.GenerateWarningMessage(
+				fmt.Errorf("error in DeclStmt: %v", err), n))
+			err = nil // Error is ignored
 			return
 		}
-		stmt = stmts[len(stmts)-1]
-		if len(stmts) > 1 {
-			preStmts = stmts[0 : len(stmts)-2]
+		switch len(stmts) {
+		case 0:
+			return
+		case 1:
+			stmt = stmts[0]
+		default:
+			stmt = stmts[0]
+			postStmts = stmts[1:]
 		}
 		return
 	}
@@ -663,27 +655,18 @@ func transpileToNode(node ast.Node, p *program.Program) (
 }
 
 func transpileStmts(nodes []ast.Node, p *program.Program) (stmts []goast.Stmt, err error) {
-	defer func() {
+	for _, s := range nodes {
+		if s == nil {
+			continue
+		}
+		stmt, preStmts, postStmts, err := transpileToStmt(s, p)
 		if err != nil {
 			p.AddMessage(p.GenerateWarningMessage(
-				fmt.Errorf("error in transpileToStmts: %v", err), nodes[0]))
+				fmt.Errorf("transpileToStmts: %v", err), nodes[0]))
 			err = nil // Error is ignored
+			continue
 		}
-	}()
-
-	for _, s := range nodes {
-		if s != nil {
-			var (
-				stmt      goast.Stmt
-				preStmts  []goast.Stmt
-				postStmts []goast.Stmt
-			)
-			stmt, preStmts, postStmts, err = transpileToStmt(s, p)
-			if err != nil {
-				return
-			}
-			stmts = append(stmts, combineStmts(stmt, preStmts, postStmts)...)
-		}
+		stmts = append(stmts, combineStmts(preStmts, stmt, postStmts)...)
 	}
 
 	return stmts, nil
diff --git a/transpiler/util.go b/transpiler/util.go
index 9a29b7b..e19127a 100644
--- a/transpiler/util.go
+++ b/transpiler/util.go
@@ -55,7 +55,7 @@ func nilFilterStmts(stmts []goast.Stmt) (out []goast.Stmt) {
 }
 
 // combineStmts - combine elements to slice
-func combineStmts(stmt goast.Stmt, preStmts, postStmts []goast.Stmt) (stmts []goast.Stmt) {
+func combineStmts(preStmts []goast.Stmt, stmt goast.Stmt, postStmts []goast.Stmt) (stmts []goast.Stmt) {
 	stmts = make([]goast.Stmt, 0, 1+len(preStmts)+len(postStmts))
 
 	preStmts = nilFilterStmts(preStmts)


Test patch:
diff --git a/tests/code_quality/ap.go.expected b/tests/code_quality/ap.go.expected
index 541b46e..fe263c2 100644
--- a/tests/code_quality/ap.go.expected
+++ b/tests/code_quality/ap.go.expected
@@ -35,49 +35,49 @@ func get() int32 {
 
 // main - transpiled function from  C4GO/tests/code_quality/ap.c:19
 func main() {
-	var i1 int32 = 42
 	// value
+	var i1 int32 = 42
 	a(c4goUnsafeConvert_int32(&i1))
 	b(c4goUnsafeConvert_int32(&i1), 1)
-	var i2 []int32 = []int32{11, 22}
 	// C-array
+	var i2 []int32 = []int32{11, 22}
 	a(i2)
 	b(i2, 2)
-	var i3 []int32 = c4goUnsafeConvert_int32(&i1)
 	// C-pointer from value
+	var i3 []int32 = c4goUnsafeConvert_int32(&i1)
 	a(i3)
 	b(i3, 1)
-	var i4 []int32 = i2
 	// C-pointer from array
+	var i4 []int32 = i2
 	a(i4)
 	b(i4, 2)
-	var i5 []int32 = i2[1:]
 	// C-pointer from array
+	var i5 []int32 = i2[1:]
 	a(i5)
 	b(i5, 1)
-	var i6 []int32 = i5[0+1:]
 	// pointer arithmetic
+	var i6 []int32 = i5[0+1:]
 	a(i6)
 	b(i6, 1)
+	// pointer arithmetic
 	var val int32 = 2 - 2
 	var i7 []int32 = c4goPointerArithInt32Slice(i5, int(1+(1-1)+val+0*(100-2)+0+0-0*0))
-	// pointer arithmetic
 	a(i7)
 	b(i7, 1)
-	var i8 []int32 = i5[0+1+0:]
 	// pointer arithmetic
+	var i8 []int32 = i5[0+1+0:]
 	a(i8)
 	b(i8, 1)
-	var i9 []int32 = []int32{i3[0], i3[0+1]}
 	// pointer arithmetic
+	var i9 []int32 = []int32{i3[0], i3[0+1]}
 	a(i9)
 	b(i9, 1)
-	var i10 []int32 = i5[1+0+0+5*get()+get()+(12+3)*get():]
 	// pointer arithmetic
+	var i10 []int32 = i5[1+0+0+5*get()+get()+(12+3)*get():]
 	a(i10)
 	b(i10, 1)
-	var i11 []int32 = c4goPointerArithInt32Slice(i5, int(1+0+0+5*get()+get()-(12+3)*get()))
 	// pointer arithmetic
+	var i11 []int32 = c4goPointerArithInt32Slice(i5, int(1+0+0+5*get()+get()-(12+3)*get()))
 	a(i11)
 	b(i11, 1)
 	return
diff --git a/tests/code_quality/comments.c b/tests/code_quality/comments.c
new file mode 100644
index 0000000..98e0316
--- /dev/null
+++ b/tests/code_quality/comments.c
@@ -0,0 +1,72 @@
+// Taked from TestBookSources/testdata/git-source/VasielBook/Глава_4/4.11/main.c
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Динамический массив как результат функции */
+
+/*
+ * Функция результатом возвращает динамический массив,
+ * заполненный числами Фибоначчи
+ */
+
+int* fibs(int n)
+{
+    /* Если указан некоректный раззмер массива */
+    if (n <= 0)
+        return 0;
+
+    /* Создание динамического массива */
+    int* p = malloc(n * sizeof(int));
+
+    /* Первый элемент массива */
+    p[0] = 1;
+
+    /* Если в массиве есть второй элемент */
+    if (n > 1)
+        p[1] = 1;
+
+    /* Индексная переменная */
+    int k;
+
+    /* Заполнение прочих элементов массива */
+    for (k = 2; k < n; k++)
+        p[k] = p[k - 1] + p[k - 2];
+
+    return p;
+}
+
+// main function
+//
+// begin of program
+
+int main(void)
+{
+    /* Указатель для записи результатов вызова */
+    int* nums;
+
+    /* Переменная для записи размера массива */
+    int size;
+
+    /* Считывание размера массива */
+    printf("Укажите размер массива: ");
+    scanf("%d", &size);
+
+    /* Индексная переменная */
+    int k;
+
+    /* Отображение элементов массива */
+    for (k = 0; k < size; k++)
+        printf("| %d ", nums[k]);
+
+    if (size >= 1)
+        printf("|\n");
+
+    /* Удаление массива из памяти */
+    if (nums) {
+        free(nums);
+        printf("Динамический массив удалён\n");
+    } else
+        printf("Массив не был создан\n");
+
+    return 0;
+}
diff --git a/tests/code_quality/comments.go.expected b/tests/code_quality/comments.go.expected
new file mode 100644
index 0000000..dad0b42
--- /dev/null
+++ b/tests/code_quality/comments.go.expected
@@ -0,0 +1,82 @@
+//
+//	Package - transpiled by c4go
+//
+//	If you have found any issues, please raise an issue at:
+//	https://github.com/Konstantin8105/c4go/
+//
+
+package code_quality
+
+import "unsafe"
+import "github.com/Konstantin8105/c4go/noarch"
+import "fmt"
+
+// fibs - transpiled function from  C4GO/tests/code_quality/comments.c:12
+func fibs(n int32) []int32 {
+	if n <= 0 {
+		// Taked from TestBookSources/testdata/git-source/VasielBook/Глава_4/4.11/main.c
+		// Динамический массив как результат функции
+		//
+		// * Функция результатом возвращает динамический массив,
+		// * заполненный числами Фибоначчи
+		//
+		// Если указан некоректный раззмер массива
+		return nil
+	}
+	// Создание динамического массива
+	var p []int32 = make([]int32, uint32(n)*uint32(1))
+	// Первый элемент массива
+	p[0] = 1
+	if n > 1 {
+		// Если в массиве есть второй элемент
+		p[1] = 1
+	}
+	// Индексная переменная
+	var k int32
+	{
+		// Заполнение прочих элементов массива
+		for k = 2; k < n; k++ {
+			p[k] = p[k-1] + p[k-2]
+		}
+	}
+	return p
+}
+
+// main - transpiled function from  C4GO/tests/code_quality/comments.c:42
+func main() {
+	defer noarch.AtexitRun()
+	// main function
+	//
+	// begin of program
+	// Указатель для записи результатов вызова
+	var nums []int32
+	// Переменная для записи размера массива
+	var size int32
+	// Считывание размера массива
+	fmt.Printf("Укажите размер массива: ")
+	noarch.Scanf([]byte("%d\x00"), c4goUnsafeConvert_int32(&size))
+	// Индексная переменная
+	var k int32
+	{
+		// Отображение элементов массива
+		for k = 0; k < size; k++ {
+			noarch.Printf([]byte("| %d \x00"), nums[k])
+		}
+	}
+	if size >= 1 {
+		fmt.Printf("|\n")
+	}
+	if nums != nil {
+		_ = nums
+		// Удаление массива из памяти
+		fmt.Printf("Динамический массив удалён\n")
+	} else {
+		fmt.Printf("Массив не был создан\n")
+	}
+	return
+}
+
+// c4goUnsafeConvert_int32 : created by c4go
+func c4goUnsafeConvert_int32(c4go_name *int32) []int32 {
+	return (*[1000000]int32)(unsafe.Pointer(c4go_name))[:]
+}
diff --git a/tests/code_quality/operators.go.expected b/tests/code_quality/operators.go.expected
index fc73ea1..6f662d7 100644
--- a/tests/code_quality/operators.go.expected
+++ b/tests/code_quality/operators.go.expected
@@ -32,6 +32,7 @@ func operators_equals() {
 	var w3 int32 = int32(int64(42))
 	var w4 int64 = int64(42)
 	var w5 int16 = int16(int64(42))
+	// zero value
 	var s1 int32
 	var s2 uint32
 	var s3 int32
@@ -56,10 +57,11 @@ func operators_equals() {
 	var r4 [][][][]int32
 	var r5 [][][][][]int32
 	var r6 [][][][][][]int32
-	// zero value
 	// function
 	f(42)
+	// array
 	var arr []float32 = make([]float32, 500)
+	// simplificator
 	var ss []byte = []byte("words\x00")
 	var cc int32 = int32(uint8((func() []byte {
 		defer func() {
@@ -68,6 +70,3 @@ func operators_equals() {
 		return ss
 	}())[0]))
 }
-
-// array
-// simplificator
diff --git a/tests/code_quality/unsafe.go.expected b/tests/code_quality/unsafe.go.expected
index 01f3d03..f7c8bf6 100644
--- a/tests/code_quality/unsafe.go.expected
+++ b/tests/code_quality/unsafe.go.expected
@@ -46,9 +46,9 @@ type db = float64
 
 // test_char - transpiled function from  C4GO/tests/code_quality/unsafe.c:22
 func test_char() {
+	// integers
 	var t byte
 	var pt []byte = c4goUnsafeConvert_byte(&t)
-	// integers
 	_ = t
 	_ = pt
 }
@@ -103,9 +103,9 @@ func test_lli() {
 
 // test_f - transpiled function from  C4GO/tests/code_quality/unsafe.c:31
 func test_f() {
+	// floats
 	var t float32
 	var pt []float32 = c4goUnsafeConvert_float32(&t)
-	// floats
 	_ = t
 	_ = pt
 }
@@ -128,27 +128,27 @@ func test_ld() {
 
 // test_struct - transpiled function from  C4GO/tests/code_quality/unsafe.c:36
 func test_struct() {
+	// struct
 	var t str
 	var pt []str = c4goUnsafeConvert_str(&t)
-	// struct
 	_ = t
 	_ = pt
 }
 
 // test_un - transpiled function from  C4GO/tests/code_quality/unsafe.c:39
 func test_un() {
+	// union
 	var t un
 	var pt []un = c4goUnsafeConvert_un(&t)
-	// union
 	_ = t
 	_ = pt
 }
 
 // test_typedef - transpiled function from  C4GO/tests/code_quality/unsafe.c:42
 func test_typedef() {
+	// typedef
 	var t db
 	var pt []db = c4goUnsafeConvert_float64(&t)
-	// typedef
 	_ = t
 	_ = pt
 }
diff --git a/tests/struct.c b/tests/struct.c
index a190665..b3bd89e 100644
--- a/tests/struct.c
+++ b/tests/struct.c
@@ -751,6 +751,53 @@ void test_struct_bit()
     is_eq((int)(bs.b), 2);
 }
 
+union MyNumber {
+    int n;
+    char s[200];
+} obj;
+
+union MyNumber getNumber(char x, int state)
+{
+    union MyNumber tmp;
+    if (state)
+        tmp.n = (int)(x + 10 - 'A');
+    else {
+        switch (x) {
+        case 'A':
+            strcpy(tmp.s, "десять");
+            break;
+        case 'B':
+            strcpy(tmp.s, "одиннадцать");
+            break;
+        case 'C':
+            strcpy(tmp.s, "двенадцать");
+            break;
+        case 'D':
+            strcpy(tmp.s, "тринадцать");
+            break;
+        case 'E':
+            strcpy(tmp.s, "четырнадцать");
+            break;
+        case 'F':
+            strcpy(tmp.s, "пятнадцать");
+        }
+    }
+    return tmp;
+}
+
+void test_union_function()
+{
+    char k;
+    for (k = 'A'; k <= 'F'; k++) {
+        union MyNumber m = getNumber(k, 1);
+        printf("%c - %d\n", k, m.n);
+    }
+    for (k = 'A'; k <= 'F'; k++) {
+        obj = getNumber(k, 0);
+        printf("%c - %s\n", k, obj.s);
+    }
+}
+
 int main()
 {
     plan(127);
@@ -1161,6 +1208,7 @@ int main()
     typedef_struct_with_typedef_union();
     test_struct_with_func();
     test_struct_bit();
+    test_union_function();
 
     done_testing();
 }