diff --git a/src/main/java/dk/camelot64/kickc/model/Initializers.java b/src/main/java/dk/camelot64/kickc/model/Initializers.java index d5b5789a3..393a214f2 100644 --- a/src/main/java/dk/camelot64/kickc/model/Initializers.java +++ b/src/main/java/dk/camelot64/kickc/model/Initializers.java @@ -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 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 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 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 constMemberMap = new LinkedHashMap<>(); + boolean allConst = true; + // Constantified values in a list + List constantifiedList = new ArrayList<>(); + // Map filled if all member values become constant + LinkedHashMap constMemberMap = new LinkedHashMap<>(); + Iterator memberDefIt = memberDefinitions.iterator(); + Iterator 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 constantifiedList = new ArrayList<>(); - // Map filled if all member values become constant - LinkedHashMap constMemberMap = new LinkedHashMap<>(); - Iterator memberDefIt = memberDefinitions.iterator(); - Iterator 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)); } } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ValueListUnionDesignator.java b/src/main/java/dk/camelot64/kickc/model/values/UnionDesignator.java similarity index 53% rename from src/main/java/dk/camelot64/kickc/model/values/ValueListUnionDesignator.java rename to src/main/java/dk/camelot64/kickc/model/values/UnionDesignator.java index ae42ea218..6811766db 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ValueListUnionDesignator.java +++ b/src/main/java/dk/camelot64/kickc/model/values/UnionDesignator.java @@ -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. - *

- * 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 asList(RValue rValue) { - final ArrayList 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(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 4357e149c..3f570bead 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1917,7 +1917,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor