1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-12 11:37:43 +00:00

FlightControl fix for #678.

This commit is contained in:
jespergravgaard 2023-04-04 13:11:36 +02:00
parent 3c52043744
commit b85e6fc715
3 changed files with 74 additions and 73 deletions

View File

@ -89,6 +89,8 @@ public class Initializers {
return new ConstantCastValue(toType, (ConstantValue) constantSub);
}
}
} else if(initValue instanceof UnionDesignator) {
initValue = constantifyUnion((UnionDesignator) initValue, (SymbolTypeStruct) typeSpec.getType(), program, source);
} else if(initValue instanceof ValueList) {
ValueList initList = (ValueList) initValue;
if(typeSpec.getType() instanceof SymbolTypePointer && ((SymbolTypePointer) typeSpec.getType()).getArraySpec() != null) {
@ -96,7 +98,7 @@ public class Initializers {
initValue = constantifyArray(initList, (SymbolTypePointer) typeSpec.getType(), program, source);
} else if(typeSpec.getType() instanceof SymbolTypeStruct) {
// Type is a struct
initValue = constantifyStruct(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
initValue = constantifyStructOrUnion(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
} else {
throw new CompileError("Value list cannot initialize type " + typeSpec.getType(), source);
}
@ -127,6 +129,42 @@ public class Initializers {
return initValue;
}
/**
* Convert as much as possible of a struct to constants.
*
* @param unionInit The value list
* @param structType The struct type
* @param program The program
* @param source The source line
* @return The constantified value
*/
private static RValue constantifyUnion(UnionDesignator unionInit, SymbolTypeStruct structType, Program program, StatementSource source) {
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
final String memberName = unionInit.getMemberName();
final RValue initValue = unionInit.getMemberValue();
Variable memberDef = null;
for(Variable definition : memberDefinitions) {
if(definition.getLocalName().equals(memberName)) {
memberDef = definition;
}
}
if(memberDef==null)
throw new CompileError( "Union member not found", source);
RValue constantifiedMemberValue = constantify(initValue, new ValueTypeSpec(memberDef.getType()), program, source);
if(constantifiedMemberValue instanceof ConstantValue) {
LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
constMemberMap.put(memberDef.getRef(), (ConstantValue) constantifiedMemberValue);
return new ConstantStructValue(structType, constMemberMap);
} else {
throw new CompileError( "Union initializer is not constant", source);
}
}
/**
* Convert as much as possible of a struct to constants.
*
@ -136,19 +174,17 @@ public class Initializers {
* @param source The source line
* @return The constantified value
*/
private static RValue constantifyStruct(ValueList valueList, SymbolTypeStruct structType, Program program, StatementSource source) {
private static RValue constantifyStructOrUnion(ValueList valueList, SymbolTypeStruct structType, Program program, StatementSource source) {
// Recursively cast all sub-elements
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
int structInitNeedSize = structDefinition.isUnion() ? 1 : memberDefinitions.size();
if(structInitNeedSize != valueList.getList().size()) {
if(structDefinition.isUnion()) {
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);
}
throw new CompileError(
"Union initializer has wrong size. One value is required.\n" +
" Union initializer: " + valueList.toString(program),
source);
} else {
throw new CompileError(
"Struct initializer has wrong size (" + valueList.getList().size() + "), " +
@ -159,55 +195,29 @@ public class Initializers {
}
}
if(valueList instanceof ValueListUnionDesignator) {
ValueListUnionDesignator unionInit = (ValueListUnionDesignator) valueList;
final String memberName = unionInit.getMemberName();
final RValue initValue = unionInit.getMemberValue();
Variable memberDef = null;
for(Variable definition : memberDefinitions) {
if(definition.getLocalName().equals(memberName)) {
memberDef = definition;
}
}
if(memberDef==null)
throw new CompileError( "Union member not found", source);
RValue constantifiedMemberValue = constantify(initValue, new ValueTypeSpec(memberDef.getType()), program, source);
if(constantifiedMemberValue instanceof ConstantValue) {
LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
boolean allConst = true;
// Constantified values in a list
List<RValue> constantifiedList = new ArrayList<>();
// Map filled if all member values become constant
LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
Iterator<Variable> memberDefIt = memberDefinitions.iterator();
Iterator<RValue> valueIt = valueList.getList().iterator();
for(int i = 0; i < structInitNeedSize; i++) {
Variable memberDef = memberDefIt.next();
RValue memberValue = valueIt.next();
RValue constantifiedMemberValue = constantify(memberValue, new ValueTypeSpec(memberDef.getType()), program, source);
constantifiedList.add(constantifiedMemberValue);
if(constantifiedMemberValue instanceof ConstantValue)
constMemberMap.put(memberDef.getRef(), (ConstantValue) constantifiedMemberValue);
return new ConstantStructValue(structType, constMemberMap);
} else {
throw new CompileError( "Union initializer is not constant", source);
}
else
allConst = false;
}
if(allConst) {
// Constant struct
return new ConstantStructValue(structType, constMemberMap);
} else {
boolean allConst = true;
// Constantified values in a list
List<RValue> constantifiedList = new ArrayList<>();
// Map filled if all member values become constant
LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
Iterator<Variable> memberDefIt = memberDefinitions.iterator();
Iterator<RValue> valueIt = valueList.getList().iterator();
for(int i = 0; i < structInitNeedSize; i++) {
Variable memberDef = memberDefIt.next();
RValue memberValue = valueIt.next();
RValue constantifiedMemberValue = constantify(memberValue, new ValueTypeSpec(memberDef.getType()), program, source);
constantifiedList.add(constantifiedMemberValue);
if(constantifiedMemberValue instanceof ConstantValue)
constMemberMap.put(memberDef.getRef(), (ConstantValue) constantifiedMemberValue);
else
allConst = false;
}
if(allConst) {
// Constant struct
return new ConstantStructValue(structType, constMemberMap);
} else {
// Constantified list with a cast
return new CastValue(structType, new ValueList(constantifiedList));
}
// Constantified list with a cast
return new CastValue(structType, new ValueList(constantifiedList));
}
}

View File

@ -2,33 +2,24 @@ package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.Program;
import java.util.ArrayList;
import java.util.List;
/**
* A union designator initializer.
* <p>
* The init list will have length one.
*/
public class ValueListUnionDesignator extends ValueList {
public class UnionDesignator implements RValue {
private String memberName;
private final String memberName;
public ValueListUnionDesignator(String memberName, RValue rValue) {
super(asList(rValue));
private final RValue rValue;
public UnionDesignator(String memberName, RValue rValue) {
this.memberName = memberName;
}
static List<RValue> asList(RValue rValue) {
final ArrayList<RValue> list = new ArrayList<>();
list.add(rValue);
return list;
this.rValue = rValue;
}
public String getMemberName() { return memberName; }
public RValue getMemberValue() {
return getList().get(0);
return rValue;
}
@Override
@ -37,7 +28,7 @@ public class ValueListUnionDesignator extends ValueList {
out.append("{ ");
out.append(memberName);
out.append("=");
out.append(getList().get(0).toString(program));
out.append(rValue.toString(program));
out.append(" }");
return out.toString();
}

View File

@ -1917,7 +1917,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
public RValue visitInitUnion(KickCParser.InitUnionContext ctx) {
final String memberName = ctx.NAME().getText();
final RValue rValue = (RValue) visit(ctx.expr());
return new ValueListUnionDesignator(memberName, rValue);
return new UnionDesignator(memberName, rValue);
}
@Override