mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Implemented C99 compatible union initializer method, using .member= syntax...
(cherry picked from commit f52f851127ab06064c010d310ee7d87f78e1f303)
This commit is contained in:
parent
7098b28cb2
commit
51623c3657
@ -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
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user