1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

Implemented C99 compatible union initializer method, using .member= syntax...

(cherry picked from commit f52f851127ab06064c010d310ee7d87f78e1f303)
This commit is contained in:
Sven Van de Velde 2023-04-02 12:43:18 +02:00 committed by Flight_Control
parent 7098b28cb2
commit 51623c3657
5 changed files with 135 additions and 9 deletions

View File

@ -217,6 +217,15 @@ commaExpr
| commaExpr COMMA expr #commaSimple
;
initMemberExpr
: expr
;
initExpr
: (DOT initMemberExpr ASSIGN)? expr
;
expr
: PAR_BEGIN commaExpr PAR_END #exprPar
| expr DOT NAME #exprDot
@ -243,9 +252,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 expr (COMMA expr )* COMMA? CURLY_END #initList
| NAME #exprId
| NUMBER #exprNumber
| STRING+ #exprString

View File

@ -0,0 +1,34 @@
struct M {
unsigned int flight;
signed char turn;
unsigned char speed;
};
struct T {
signed char turn;
unsigned char radius;
unsigned char speed;
};
struct E {
unsigned char explode;
};
union A {
struct M move;
struct T turn;
struct E end;
};
struct F {
union A action;
unsigned char type;
unsigned char next;
};
struct F action_flightpath_001[] = {
{ .move={ action_move_00 }, STAGE_ACTION_MOVE, 1 },
{ { action_end } , STAGE_ACTION_END, 0 }
};

View File

@ -143,10 +143,12 @@ public class Initializers {
int structInitNeedSize = structDefinition.isUnion() ? 1 : memberDefinitions.size();
if(structInitNeedSize != valueList.getList().size()) {
if(structDefinition.isUnion()) {
throw new CompileError(
"Union initializer has too many values, since only one is allowed.\n" +
" Union initializer: " + valueList.toString(program),
source);
if(valueList.getList().size()>1) {
throw new CompileError(
"Union initializer has too many values, since only one is allowed.\n" +
" Union initializer: " + valueList.toString(program),
source);
}
} else {
throw new CompileError(
"Struct initializer has wrong size (" + valueList.getList().size() + "), " +
@ -165,8 +167,19 @@ public class Initializers {
Iterator<Variable> memberDefIt = memberDefinitions.iterator();
Iterator<RValue> valueIt = valueList.getList().iterator();
for(int i = 0; i < structInitNeedSize; i++) {
Variable memberDef = memberDefIt.next();
Variable memberDef = null;
RValue memberValue = valueIt.next();
String memberUnion = ((ValueStructList)valueList).getMember(memberValue);
if(memberUnion != null) {
while(memberDefIt.hasNext()) {
memberDef = memberDefIt.next();
if (memberDef.getLocalName().contentEquals(memberUnion.toString())) {
break;
}
}
} else {
memberDef = memberDefIt.next();
}
RValue constantifiedMemberValue = constantify(memberValue, new ValueTypeSpec(memberDef.getType()), program, source);
constantifiedList.add(constantifiedMemberValue);
if(constantifiedMemberValue instanceof ConstantValue)

View File

@ -0,0 +1,46 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.Program;
import java.util.HashMap;
import java.util.List;
/**
* A list of sub-values.
* Used for struct value initializers.
*/
public class ValueStructList extends ValueList {
private HashMap<RValue, String> members;
public ValueStructList(HashMap<RValue, String> members, List<RValue> list) {
super(list);
this.members = members;
}
public HashMap<RValue, String> getMembers() {
return members;
}
public String getMember(RValue init) { return members.get(init); }
@Override
public String toString(Program program) {
StringBuilder out = new StringBuilder();
boolean first = true;
out.append("{ ");
for(RValue constantValue : getList()) {
if(!first) {
out.append(", ");
}
first = false;
out.append(constantValue.toString(program));
}
out.append(" }");
return out.toString();
}
@Override
public String toString() {
return toString(null);
}
}

View File

@ -1913,14 +1913,38 @@ 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<>();
for(KickCParser.ExprContext initializer : ctx.expr()) {
RValue rValue = (RValue) visit(initializer);
HashMap<RValue, String> members = 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());
}
}
return new ValueList(initValues);
return new ValueStructList(members, initValues);
}
@Override