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:
parent
3c52043744
commit
b85e6fc715
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user