1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-21 14:30:21 +00:00

Implemented C99 compatible union initializer method.

- Added test cases.
- Reworked parser.
- Added code redesign to avoid crashes in Initializers.java.
This commit is contained in:
Flight_Control 2023-04-04 09:30:40 +02:00
parent 9db2d9b960
commit c5f260e882
32 changed files with 663 additions and 42 deletions

View File

@ -217,12 +217,9 @@ commaExpr
| commaExpr COMMA expr #commaSimple
;
initMemberExpr
: expr
;
initExpr
: (DOT initMemberExpr ASSIGN)? expr
: (DOT expr ASSIGN)? expr
;
@ -252,9 +249,9 @@ expr
| expr ( '&&' ) expr #exprBinary
| expr ( '||' ) expr #exprBinary
| expr '?' expr COLON expr #exprTernary
| CURLY_BEGIN initExpr (COMMA initExpr )* COMMA? CURLY_END #initList
| <assoc=right> expr '=' expr #exprAssignment
| <assoc=right> expr ASSIGN_COMPOUND expr #exprAssignmentCompound
| CURLY_BEGIN initExpr (COMMA initExpr )* COMMA? CURLY_END #initList
| NAME #exprId
| NUMBER #exprNumber
| STRING+ #exprString

View File

@ -169,21 +169,25 @@ public class Initializers {
for(int i = 0; i < structInitNeedSize; i++) {
Variable memberDef = null;
RValue memberValue = valueIt.next();
String memberUnionName = ((ValueStructList)valueList).getMember(memberValue);
if(memberUnionName != null) {
boolean found = false;
while (memberDefIt.hasNext()) {
memberDef = memberDefIt.next();
if (memberDef.getLocalName().contentEquals(memberUnionName)) {
found = true;
break;
if(structDefinition.isUnion()) {
String memberUnionName = ((ValueStructList)valueList).getMember(memberValue);
if(memberUnionName != null) {
boolean found = false;
while (memberDefIt.hasNext()) {
memberDef = memberDefIt.next();
if (memberDef.getLocalName().contentEquals(memberUnionName)) {
found = true;
break;
}
}
if (!found)
throw new CompileError(
"Union initializer cannot find member field " + memberUnionName + "\n" +
" Union initializer: " + valueList.toString(program),
source);
} else {
memberDef = memberDefIt.next();
}
if(!found)
throw new CompileError(
"Union initializer cannot find member field " + memberUnionName + "\n" +
" Union initializer: " + valueList.toString(program),
source);
} else {
memberDef = memberDefIt.next();
}

View File

@ -1913,38 +1913,24 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public String visitInitExpr(KickCParser.InitExprContext ctx) {
List<RValue> initValues = new ArrayList<>();
HashMap<String, RValue> members = new HashMap<>();
String member = null;
if(ctx.initMemberExpr() != null) {
member = ctx.initMemberExpr().getText();
}
return member;
}
@Override
public RValue visitInitList(KickCParser.InitListContext ctx) {
List<RValue> initValues = new ArrayList<>();
HashMap<RValue, String> members = new HashMap<>();
HashMap<RValue, String> initDesignators = new HashMap<>();
for(KickCParser.InitExprContext initializer : ctx.initExpr()) {
RValue member = null;
String initString = initializer.getText();
if (initializer.initMemberExpr() != null) {
if(initializer.initMemberExpr().isEmpty() == false) {
member = (RValue) visit(initializer.initMemberExpr());
}
}
RValue rValue = (RValue) visit(initializer.expr());
initValues.add(rValue);
if(member!=null) {
members.put(rValue, member.toString());
if (initializer.expr().size() == 2) {
RValue member = (RValue) visit(initializer.expr(0));
RValue rValue = (RValue) visit(initializer.expr(1));
initValues.add(rValue);
initDesignators.put(rValue, member.toString());
} else {
RValue rValue = (RValue) visit(initializer.expr(0));
initValues.add(rValue);
}
}
return new ValueStructList(members, initValues);
return new ValueStructList(initDesignators, initValues);
}
@Override

View File

@ -2541,6 +2541,26 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("weeip-bbslist.c");
}
@Test
public void testUnion12() throws IOException {
compileAndCompare("union-12.c");
}
@Test
public void testUnion11() throws IOException {
compileAndCompare("union-11.c");
}
@Test
public void testUnion10() throws IOException {
compileAndCompare("union-10.c");
}
@Test
public void testUnion9() throws IOException {
compileAndCompare("union-9.c");
}
@Test
public void testUnion8() throws IOException {
compileAndCompare("union-8.c");

27
src/test/kc/union-10.c Normal file
View File

@ -0,0 +1,27 @@
// More extensive union with C99 style designator initialization behaviour of the second element.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
union Data data = { .t={1,2,3,4} };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

27
src/test/kc/union-11.c Normal file
View File

@ -0,0 +1,27 @@
// More extensive union with C99 style designator initialization behaviour of the first element.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
union Data data = { .m={1,2,3} };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

29
src/test/kc/union-12.c Normal file
View File

@ -0,0 +1,29 @@
// More extensive union with C99 style designator initialization behaviour using const expressions.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
const struct Move move = {1,2,3};
union Data data = { .m=move };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

14
src/test/kc/union-9.c Normal file
View File

@ -0,0 +1,14 @@
// Minimal union with C99 style designator initialization behaviour.
union Data {
char b;
unsigned w;
};
union Data data = { .w=1234 };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.b;
}

View File

@ -0,0 +1,29 @@
// File Comments
// More extensive union with C99 style designator initialization behaviour.
// Upstart
.cpu _65c02
// Commodore 64 PRG executable file
.file [name="union-10.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3, 4

View File

@ -0,0 +1,67 @@
<C64debugger version="1.0">
<Sources values="INDEX,FILE">
0,KickAss.jar:/include/autoinclude.asm
1,D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target\union-10.asm
</Sources>
<Segment name="Default" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
</Segment>
<Segment name="Program" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
<Block name="Data">
$0814,$0817,1,29,9,29,13
</Block>
</Segment>
<Segment name="Basic" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
</Segment>
<Segment name="Code" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
</Segment>
<Segment name="Data" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Data">
$0814,$0817,1,29,9,29,13
</Block>
</Segment>
<Labels values="SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
Basic,$0400,SCREEN,1,14,10,14,15
Code,$080d,main,1,17,1,17,5
Basic,$080b,upstartEnd,0,43,1,43,11
Data,$0814,data,1,29,3,29,7
</Labels>
<Breakpoints values="SEGMENT,ADDRESS,ARGUMENT">
</Breakpoints>
<Watchpoints values="SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT">
</Watchpoints>
</C64debugger>

View File

@ -0,0 +1,23 @@
Output dir: D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target
parsing
flex pass 1
flex pass 2
flex pass 3
Output pass
Writing prg file: union-10.prg
Memory Map
----------
Program-segment:
Basic-segment:
$0801-$080c Basic
Code-segment:
$080d-$0813 Code
Data-segment:
$0814-$0817 Data
Writing Vice symbol file: union-10.vs
Writing Symbol file: union-10.sym

Binary file not shown.

View File

@ -0,0 +1,4 @@
.label SCREEN=$400
.label data=$814
.label main=$80d {
}

View File

@ -0,0 +1,4 @@
al C:400 .SCREEN
al C:814 .data
al C:80b .upstartEnd
al C:80d .main

View File

@ -0,0 +1,30 @@
// File Comments
// More extensive union with C99 style designator initialization behaviour.
// Upstart
.cpu _65c02
// Commodore 64 PRG executable file
.file [name="union-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3
.fill 1, 0

View File

@ -0,0 +1,69 @@
<C64debugger version="1.0">
<Sources values="INDEX,FILE">
0,KickAss.jar:/include/autoinclude.asm
1,D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target\union-11.asm
</Sources>
<Segment name="Default" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
</Segment>
<Segment name="Program" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
<Block name="Data">
$0814,$0816,1,29,9,29,13
$0817,$0817,1,30,3,30,7
</Block>
</Segment>
<Segment name="Basic" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
</Segment>
<Segment name="Code" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
</Segment>
<Segment name="Data" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Data">
$0814,$0816,1,29,9,29,13
$0817,$0817,1,30,3,30,7
</Block>
</Segment>
<Labels values="SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
Basic,$0400,SCREEN,1,14,10,14,15
Code,$080d,main,1,17,1,17,5
Basic,$080b,upstartEnd,0,43,1,43,11
Data,$0814,data,1,29,3,29,7
</Labels>
<Breakpoints values="SEGMENT,ADDRESS,ARGUMENT">
</Breakpoints>
<Watchpoints values="SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT">
</Watchpoints>
</C64debugger>

View File

@ -0,0 +1,23 @@
Output dir: D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target
parsing
flex pass 1
flex pass 2
flex pass 3
Output pass
Writing prg file: union-11.prg
Memory Map
----------
Program-segment:
Basic-segment:
$0801-$080c Basic
Code-segment:
$080d-$0813 Code
Data-segment:
$0814-$0817 Data
Writing Vice symbol file: union-11.vs
Writing Symbol file: union-11.sym

Binary file not shown.

View File

@ -0,0 +1,4 @@
.label SCREEN=$400
.label data=$814
.label main=$80d {
}

View File

@ -0,0 +1,4 @@
al C:400 .SCREEN
al C:814 .data
al C:80b .upstartEnd
al C:80d .main

View File

@ -0,0 +1,30 @@
// File Comments
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Upstart
.cpu _65c02
// Commodore 64 PRG executable file
.file [name="union-12.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
move: .byte 1, 2, 3
data: .fill 1, 0

View File

@ -0,0 +1,70 @@
<C64debugger version="1.0">
<Sources values="INDEX,FILE">
0,KickAss.jar:/include/autoinclude.asm
1,D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target\union-12.asm
</Sources>
<Segment name="Default" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
</Segment>
<Segment name="Program" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
<Block name="Data">
$0814,$0816,1,29,9,29,13
$0817,$0817,1,30,9,30,13
</Block>
</Segment>
<Segment name="Basic" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
</Segment>
<Segment name="Code" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
</Segment>
<Segment name="Data" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Data">
$0814,$0816,1,29,9,29,13
$0817,$0817,1,30,9,30,13
</Block>
</Segment>
<Labels values="SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
Basic,$0400,SCREEN,1,14,10,14,15
Code,$080d,main,1,17,1,17,5
Basic,$080b,upstartEnd,0,43,1,43,11
Data,$0814,move,1,29,3,29,7
Data,$0817,data,1,30,3,30,7
</Labels>
<Breakpoints values="SEGMENT,ADDRESS,ARGUMENT">
</Breakpoints>
<Watchpoints values="SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT">
</Watchpoints>
</C64debugger>

View File

@ -0,0 +1,23 @@
Output dir: D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target
parsing
flex pass 1
flex pass 2
flex pass 3
Output pass
Writing prg file: union-12.prg
Memory Map
----------
Program-segment:
Basic-segment:
$0801-$080c Basic
Code-segment:
$080d-$0813 Code
Data-segment:
$0814-$0817 Data
Writing Vice symbol file: union-12.vs
Writing Symbol file: union-12.sym

Binary file not shown.

View File

@ -0,0 +1,5 @@
.label move=$814
.label SCREEN=$400
.label data=$817
.label main=$80d {
}

View File

@ -0,0 +1,5 @@
al C:814 .move
al C:400 .SCREEN
al C:817 .data
al C:80b .upstartEnd
al C:80d .main

View File

@ -0,0 +1,29 @@
// File Comments
// Minimal union with C-Standard behavior
// Upstart
.cpu _65c02
// Commodore 64 PRG executable file
.file [name="union-9.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.b
// [0] *SCREEN = *((char *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .word $4d2

View File

@ -0,0 +1,67 @@
<C64debugger version="1.0">
<Sources values="INDEX,FILE">
0,KickAss.jar:/include/autoinclude.asm
1,D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target\union-9.asm
</Sources>
<Segment name="Default" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
</Segment>
<Segment name="Program" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
<Block name="Data">
$0814,$0815,1,29,9,29,13
</Block>
</Segment>
<Segment name="Basic" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Basic">
$0801,$0802,0,38,2,38,6
$0803,$0804,0,39,5,39,9
$0805,$0805,0,40,5,40,9
$0806,$0809,0,41,2,41,6
$080a,$080a,0,42,2,42,6
$080b,$080c,0,44,5,44,9
</Block>
</Segment>
<Segment name="Code" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Code">
$080d,$080f,1,20,5,20,7
$0810,$0812,1,21,5,21,7
$0813,$0813,1,25,5,25,7
</Block>
</Segment>
<Segment name="Data" dest="" values="START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
<Block name="Data">
$0814,$0815,1,29,9,29,13
</Block>
</Segment>
<Labels values="SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2">
Basic,$0400,SCREEN,1,14,10,14,15
Code,$080d,main,1,17,1,17,5
Basic,$080b,upstartEnd,0,43,1,43,11
Data,$0814,data,1,29,3,29,7
</Labels>
<Breakpoints values="SEGMENT,ADDRESS,ARGUMENT">
</Breakpoints>
<Watchpoints values="SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT">
</Watchpoints>
</C64debugger>

View File

@ -0,0 +1,23 @@
Output dir: D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\target
parsing
flex pass 1
flex pass 2
flex pass 3
Output pass
Writing prg file: union-9.prg
Memory Map
----------
Program-segment:
Basic-segment:
$0801-$080c Basic
Code-segment:
$080d-$0813 Code
Data-segment:
$0814-$0815 Data
Writing Vice symbol file: union-9.vs
Writing Symbol file: union-9.sym

BIN
src/test/target/union-9.prg Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
.label SCREEN=$400
.label data=$814
.label main=$80d {
}

View File

@ -0,0 +1,4 @@
al C:400 .SCREEN
al C:814 .data
al C:80b .upstartEnd
al C:80d .main