Changeset 13702


Ignore:
Timestamp:
Oct 8, 2019 5:15:12 PM (2 months ago)
Author:
Jesper Mattsson
Message:

#5835:

  • Added formalized parsing of format strings to allow error checking and required casts.
  • Fixed errors in C code gen for String() operator.
  • Made format string structural parameter.
Location:
branches/dev-mj-5835
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • branches/dev-mj-5835/CHANGELOG.txt

    r13498 r13702  
    11================= Unreleased ==================
    22# Fixed ; Minor ; Compiler; #5835
    3 Format string argument to the String function is now useable.
     3Format string argument to the String function is now respected during constant evaluations.
    44
    55# Change ; Minor ; Compiler; #5830
  • branches/dev-mj-5835/Compiler/ModelicaCBackEnd/src/jastadd/CCodeGen/CCodeGenExpressions.jrag

    r13431 r13702  
    1717import java.util.Arrays;
    1818import org.jmodelica.common.ccodegen.CFuncParamDirection;
     19import org.jmodelica.util.values.CFormatSpecifier;
     20import org.jmodelica.util.collections.TransformerIterable;
    1921
    2022aspect CCodeGenExpressions {
     
    792794        genStringFormat_C(p, str, indent);
    793795        str.print(", ");
    794         genStringParts_C(p, str, indent);
     796        genStringParts_C(p, str, indent, null);
    795797        str.println(");");
    796798    }
     
    856858    @Override
    857859    public void FStringExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
    858         super.genVarDecls_C(p, str, indent);
     860        for (ASTNode ch : childrenToGenFor_C()) {
     861            ch.genVarDecls_C(p, str, indent);
     862        }
    859863        genTopStringDecl(p, str, indent);
    860864    }
     
    862866    @Override
    863867    public void FStringExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
    864         super.genTempVars_C(p, str, indent);
     868        for (ASTNode ch : childrenToGenFor_C()) {
     869            p.printPreSteps(ch, str, indent);
     870        }
    865871        genTopStringInit(p, str, indent);
    866872    }
     
    873879    @Override
    874880    public void FStringExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
    875         super.genTempFree_C(p, str, indent);
     881        for (ASTNode ch : childrenToGenFor_C()) {
     882            ch.genTempFree_C(p, str, indent);
     883        }
     884    }
     885
     886    protected Iterable<ASTNode> FStringExp.childrenToGenFor_C() {
     887        // We want to generate for NTA CFormat but not for child Format.
     888        return new TransformerIterable<ASTNode, ASTNode>(this) {
     889            private ASTNode fmt = getFormatOpt();
     890            protected ASTNode transform(ASTNode a) throws SkipException {
     891                return (a == fmt) ? getCFormatOpt() : a;
     892            }
     893        };
    876894    }
    877895
     
    947965    public void FStringExp.genStringFormat_C(CodePrinter p, CodeStream str, String indent) {
    948966        if (hasFormat()) {
    949             p.print(getFormat(), str, indent);
     967            p.print(getCFormat(), str, indent);
    950968        } else {
    951969            if (hasLeftJustified()) {
     
    9871005        if (getValue().type().isReal())
    9881006            str.print(".*");
    989         str.print(getValue().type().formatSpecifier());
     1007        str.print(getValue().type().formatConversion());
    9901008        str.print("\"");
    9911009    }
    9921010
    993     public void FExp.genStringParts_C(CodePrinter p, CodeStream str, String indent) {
     1011    public void FExp.genStringParts_C(
     1012            CodePrinter p, CodeStream str, String indent, CFormatSpecifier format) {
    9941013        // TODO: This method should dispatch to the type!
    9951014        FType t = type();
     
    10041023            str.print(", JMI_TRUE, \"true\", \"false\")");
    10051024        } else {
    1006             if (t.isInteger())
     1025            if (format != null && format.expectedType.isUnsigned()) {
     1026                str.print("(unsigned int) ");
     1027            } else if ((format == null) ? t.isInteger() : format.expectedType.isInteger()) {
    10071028                str.print("(int) ");
     1029            }
    10081030            p.print(this, str, indent);
    10091031        }
     
    10111033
    10121034    @Override
    1013     public void FStringExp.genStringParts_C(CodePrinter p, CodeStream str, String indent) {
    1014         getValue().genStringParts_C(p, str, indent);
     1035    public void FStringExp.genStringParts_C(
     1036            CodePrinter p, CodeStream str, String indent, CFormatSpecifier format) {
     1037        try {
     1038            // This depends on non-parameters being evaluatable.
     1039            format = formatSpecifier();
     1040        } catch (ConstantEvaluationException e) {
     1041            // Assume that we don't have a format that converts real -> integer.
     1042        }
     1043        getValue().genStringParts_C(p, str, indent, format);
    10151044    }
    10161045
  • branches/dev-mj-5835/Compiler/ModelicaCBackEnd/test/modelica/CCodeGenTests.mo

    r13168 r13702  
    10791079    StringCompare("      medium", String(enumVar, minimumLength=12, leftJustified=false));
    10801080
    1081     StringCompare("42",           String(intVar, format="%d"));
    1082     StringCompare("3.1400000",    String(realVar, format="%f"));
     1081    StringCompare("42",           String(intVar, format="d"));
     1082    StringCompare("3.1400000",    String(realVar, format="f"));
    10831083
    10841084annotation(__JModelica(UnitTesting(tests={
     
    1604116041    end f;
    1604216042   
    16043     Real y = f(-time, 3, true, "%g");
     16043    Real y = f(-time, 3, true, "g");
    1604416044
    1604516045annotation(__JModelica(UnitTesting(tests={
     
    1605616056    JMI_DEF(STR, s_v)
    1605716057    JMI_DEF_STR_DYNA(tmp_1)
     16058    JMI_DEF_STR_DYNA(tmp_2)
     16059    JMI_DEF_STR_DYNA(tmp_3)
    1605816060    JMI_INI(STR, s_v)
    16059     JMI_INI_STR_DYNA(tmp_1, jmi_max(7 + 1.0, i_v) + jmi_max(7 + i_v, 2.0) + jmi_max(7 + i_v, i_v) + jmi_max(7 + i_v, i_v) + 7 + i_v + 7 + 6 + 16 + jmi_max(10, 2.0) + jmi_max(10, i_v) + jmi_max(10, i_v) + 16 + jmi_max(5, 2.0) + jmi_max(5, i_v) + jmi_max(5, i_v))
    16060     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) 1.0, x_v);
    16061     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) 2.0, (int) i_v, x_v);
    16062     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(JMI_FALSE, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) i_v, x_v);
    16063     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) i_v, x_v);
    16064     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-.*g\", \"%.*g\"), (int) i_v, x_v);
    16065     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), \"%-.*g\", (int) 6, x_v);
    16066     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), fmt_v, x_v);
    16067     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*d\", \"%*d\"), (int) 2.0, (int) i_v);
    16068     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(JMI_TRUE, JMI_TRUE, \"%-*d\", \"%*d\"), (int) i_v, (int) i_v);
    16069     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*d\", \"%*d\"), (int) i_v, (int) i_v);
    16070     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), fmt_v, (int) i_v);
    16071     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*s\", \"%*s\"), (int) 2.0, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
    16072     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(JMI_TRUE, JMI_TRUE, \"%-*s\", \"%*s\"), (int) i_v, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
    16073     snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*s\", \"%*s\"), (int) i_v, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
    16074     JMI_ASG(STR, s_v, tmp_1)
     16061    JMI_INI_STR_DYNA(tmp_1, 1 + JMI_LEN(fmt_v))
     16062    snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), \"%s\", \"%\");
     16063    snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), \"%s\", fmt_v);
     16064    JMI_INI_STR_DYNA(tmp_2, 1 + JMI_LEN(fmt_v))
     16065    snprintf(JMI_STR_END(tmp_2), JMI_STR_LEFT(tmp_2), \"%s\", \"%\");
     16066    snprintf(JMI_STR_END(tmp_2), JMI_STR_LEFT(tmp_2), \"%s\", fmt_v);
     16067    JMI_INI_STR_DYNA(tmp_3, jmi_max(7 + 1.0, i_v) + jmi_max(7 + i_v, 2.0) + jmi_max(7 + i_v, i_v) + jmi_max(7 + i_v, i_v) + 7 + i_v + 7 + 6 + 16 + jmi_max(10, 2.0) + jmi_max(10, i_v) + jmi_max(10, i_v) + 16 + jmi_max(5, 2.0) + jmi_max(5, i_v) + jmi_max(5, i_v))
     16068    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) 1.0, x_v);
     16069    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) 2.0, (int) i_v, x_v);
     16070    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(JMI_FALSE, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) i_v, x_v);
     16071    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*.*g\", \"%*.*g\"), (int) i_v, (int) i_v, x_v);
     16072    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-.*g\", \"%.*g\"), (int) i_v, x_v);
     16073    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), \"%-.*g\", (int) 6, x_v);
     16074    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), tmp_1, x_v);
     16075    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*d\", \"%*d\"), (int) 2.0, (int) i_v);
     16076    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(JMI_TRUE, JMI_TRUE, \"%-*d\", \"%*d\"), (int) i_v, (int) i_v);
     16077    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*d\", \"%*d\"), (int) i_v, (int) i_v);
     16078    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), tmp_2, (int) i_v);
     16079    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*s\", \"%*s\"), (int) 2.0, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
     16080    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(JMI_TRUE, JMI_TRUE, \"%-*s\", \"%*s\"), (int) i_v, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
     16081    snprintf(JMI_STR_END(tmp_3), JMI_STR_LEFT(tmp_3), COND_EXP_EQ(b_v, JMI_TRUE, \"%-*s\", \"%*s\"), (int) i_v, COND_EXP_EQ(b_v, JMI_TRUE, \"true\", \"false\"));
     16082    JMI_ASG(STR, s_v, tmp_3)
    1607516083    JMI_RET(GEN, y_o, y_v)
    1607616084    JMI_DYNAMIC_FREE()
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/ConstantEvaluation/ConstantEvaluation.jrag

    r13506 r13702  
    2222import java.util.Map;
    2323import java.util.Set;
     24import java.util.IllegalFormatException;
    2425
    2526import org.jmodelica.util.BinaryOperation;
     
    3233import org.jmodelica.util.values.ConstantEvaluationNotReadyException;
    3334import org.jmodelica.util.values.FunctionEvaluationException;
     35import org.jmodelica.util.values.CFormatSpecifier;
    3436
    3537
     
    27942796       
    27952797        CValue cval = getValue().ceval(evaluator);
    2796         boolean isReal = getValue().type().isReal();
    2797         if (isReal) {
     2798        final CFormatSpecifier format = formatSpecifier(evaluator);
     2799       
     2800        if (!format.isValid()) {
     2801            throw new ConstantEvaluationException(format.errorMessage());
     2802        }
     2803       
     2804        // Do any necessary type conversions.
     2805        if (format.expectedType.isReal()) {
    27982806            cval = cval.convertReal();
     2807        } else if (format.expectedType.isInteger()) {
     2808            cval = cval.convertInteger();
    27992809        }
    28002810        Object value = cval.objectValue();
    2801         final String format = formatString(evaluator);
    2802         char formatChar = format.charAt(format.length() - 1);
    2803        
    2804         // Modelica allows Integer to Real conversion for formatting but not the other direction
    2805         boolean mustBeInteger = formatChar == 'd' || formatChar == 'i' || formatChar == 'o' ||
    2806             formatChar == 'x' || formatChar == 'X' || formatChar == 'u' || formatChar == 'c';
    2807         if (mustBeInteger && isReal) {
    2808             throw new ConstantEvaluationException(cval, "format the resulting value. The format '"+ format + "' requires value of Integer type but Real value is provided. ");
    2809         }
    2810 
    2811         if (getValue().type().isInteger()) {
    2812             // Java formatter do not convert types
    2813             final boolean convertToFloat = formatChar == 'e' || formatChar == 'E' ||
    2814                     formatChar == 'f' || formatChar == 'g' || formatChar == 'G';
    2815             if (convertToFloat) {
    2816                 return new CValueString(String.format((Locale) null, format, cval.realValue()));
    2817             }
    2818             if (formatChar == 'u') {
    2819                 String formatCorrect = format.substring(0, format.length()-1) + "s";
    2820                 return new CValueString(String.format((Locale) null, formatCorrect, Integer.toUnsignedLong(cval.intValue())));
    2821             }
    2822 
    2823             if (formatChar == 'i') {
    2824                 String formatCorrect = format.substring(0, format.length()-1) + "d";
    2825                 return new CValueString(String.format((Locale) null, formatCorrect, cval.intValue()));
    2826             }
     2811        if (format.expectedType.isUnsigned()) {
     2812            // Convert to the closest Java equivalent to an unsigned int.
     2813            // TODO: When we no longer need to support Java 7, use Integer.toUnsignedLong instead.
     2814            value = Long.valueOf(((Integer) value).longValue() & 0xffffffffL);
    28272815        }
    28282816       
    28292817        try {
    2830             return new CValueString(String.format((Locale) null, format, value));
    2831         } catch (java.util.IllegalFormatException e) {
    2832             throw new ConstantEvaluationException(cval,
    2833                     "format the resulting value. " + format + " is not a supported valid format string");
     2818            return new CValueString(String.format((Locale) null, format.javaFormat, value));
     2819        } catch (IllegalFormatException e) {
     2820            throw new ConstantEvaluationException("The format string \"" + format.format +
     2821                    "\" and the value " + value + " do not match in the string conversion: " + this, e);
    28342822        }
    28352823    }
     
    28442832    }
    28452833
    2846     syn String FStringExp.formatString(VariableEvaluator evaluator) {
    2847         StringBuilder buf = new StringBuilder("%");
     2834    syn CFormatSpecifier FStringExp.formatSpecifier() = formatSpecifier(defaultVariableEvaluator());
     2835
     2836    syn CFormatSpecifier FStringExp.formatSpecifier(VariableEvaluator evaluator) {
    28482837        if (hasFormat()) {
    2849             buf.append(getFormat().ceval(evaluator).stringValue());
     2838            return CFormatSpecifier.parseFormat(getFormat().ceval(evaluator).stringValue());
    28502839        } else {
    2851             int minLength = minimumLength(evaluator);
    2852             if (minLength > 0) {
    2853                 if (leftJustified(evaluator)) {
    2854                     buf.append('-');
    2855                 }
    2856                 buf.append(minLength);
    2857             }
    2858             if (getValue().type().isReal()) {
    2859                 buf.append('.');
    2860                 buf.append(significantDigits(evaluator));
    2861             }
    2862             buf.append(getValue().type().formatSpecifier());
    2863         }
    2864         return buf.toString();
     2840            FType t = getValue().type();
     2841            int m = minimumLength(evaluator);
     2842            boolean l = leftJustified(evaluator);
     2843            if (t.isReal()) {
     2844                int s = significantDigits(evaluator);
     2845                return CFormatSpecifier.realFormat(l, m, s);
     2846            } else if (t.isInteger()) {
     2847                return CFormatSpecifier.integerFormat(l, m);
     2848            } else {
     2849                return CFormatSpecifier.stringFormat(l, m);
     2850            }
     2851        }
    28652852    }
    28662853
    28672854    syn int FStringExp.minimumLength(VariableEvaluator evaluator)     =
    2868         hasMinimumLength() ? getMinimumLength().ceval(evaluator).intValue() : 0;
     2855        hasMinimumLength() ? getMinimumLength().ceval(evaluator).intValue() : 1;
    28692856    syn boolean FStringExp.leftJustified(VariableEvaluator evaluator) =
    28702857        hasLeftJustified() ? getLeftJustified().ceval(evaluator).booleanValue() : true;
    28712858    syn int FStringExp.significantDigits(VariableEvaluator evaluator) =
    28722859        hasSignificantDigits() ? getSignificantDigits().ceval(evaluator).intValue() : DEFAULT_PRECISION;
    2873     syn String FType.formatSpecifier() {
     2860    syn String FType.formatConversion() {
    28742861        throw new UnsupportedOperationException();
    28752862    }
    2876     eq FRealType.formatSpecifier()    = "g";
    2877     eq FIntegerType.formatSpecifier() = "d";
    2878     eq FBooleanType.formatSpecifier() = "s";
    2879     eq FEnumType.formatSpecifier()    = "s";
    2880     eq FStringType.formatSpecifier()  = "s";
     2863    eq FRealType.formatConversion()    = "g";
     2864    eq FIntegerType.formatConversion() = "d";
     2865    eq FBooleanType.formatConversion() = "s";
     2866    eq FEnumType.formatConversion()    = "s";
     2867    eq FStringType.formatConversion()  = "s";
    28812868    public static final int FStringExp.DEFAULT_PRECISION = 6;
    28822869
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/FlatAPI/FlatAPI.jrag

    r13456 r13702  
    44664466            return unboundCopy();
    44674467    }
     4468
     4469    /**
     4470     * The format string including the implicit leading "%", if the format argument is given.
     4471     */
     4472    syn lazy Opt<FExp> FStringExp.getCFormatOpt() {
     4473        // TODO: To save memory, this could be solved in the C code generation instead.
     4474        if (hasFormat()) {
     4475            FExp fmt = getFormat();
     4476            FExp exp = new FStringAddExp(new FStringLitExp("%"), fmt.treeCopy());
     4477            if (fmt.variability().fixedParameterOrLess()) {
     4478                try {
     4479                    exp.parent = this;
     4480                    exp = exp.ceval().buildLiteral();
     4481                } catch (ConstantEvaluationException e) {
     4482                    // If we can't evaluate, just leave it as is
     4483                }
     4484            }
     4485            return new Opt<FExp>(exp);
     4486        } else {
     4487            return new Opt<FExp>();
     4488        }
     4489    }
    44684490}
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/PrettyPrint.jrag

    r13357 r13702  
    18491849    }
    18501850
    1851     protected static final String FBuiltInFunctionCall.SEP = ", ";
    1852    
    1853     /**
    1854      * Pretty-print all arguments of function.
    1855      *
    1856      * Default implementation prints all direct FExp children (including those in Lists and Opts),
    1857      * separated by {@link #SEP}.
    1858      */
    1859     protected void FBuiltInFunctionCall.prettyPrintArguments(Printer p, CodeStream str, String indent) {
    1860         String pre = "";
    1861         for (FExp exp : myArgs()) {
    1862             str.print(pre);
    1863             p.print(exp, str, indent);
    1864             pre = SEP;
    1865         }
    1866     }
    1867    
     1851    protected static final String FBuiltInFunctionCall.SEP = ", ";
     1852
     1853    /**
     1854     * Pretty-print all arguments of function.
     1855     *
     1856     * Default implementation will in instance tree print the original arguments, and in
     1857     * flat tree print all direct FExp children (including those in Lists and Opts),
     1858     * in either case separated by {@link #SEP}.
     1859     */
     1860    protected void FBuiltInFunctionCall.prettyPrintArguments(Printer p, CodeStream str, String indent) {
     1861        String pre = "";
     1862        if (getNumOriginalArg() > 0) {
     1863            for (InstFunctionArgument arg : getOriginalArgs()) {
     1864                if (arg.isGiven()) {
     1865                    str.print(pre);
     1866                    p.print(arg, str, indent);
     1867                    pre = SEP;
     1868                }
     1869            }
     1870        } else {
     1871            for (FExp exp : myArgs()) {
     1872                str.print(pre);
     1873                p.print(exp, str, indent);
     1874                pre = SEP;
     1875            }
     1876        }
     1877    }
     1878
    18681879    protected void FInfArgsFunctionCall.prettyPrintArguments(Printer p, CodeStream str, String indent) {
    18691880        getFExps().prettyPrintWithSep(p, str, indent, SEP);
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/ast/FlatModelica.ast

    r13357 r13702  
    16061606 * String conversion operator.
    16071607 */
    1608 FStringExp : FBuiltInFunctionCall ::= Value:FExp [MinimumLength:FExp] [LeftJustified:FExp] [SignificantDigits:FExp] [Format:FExp];
     1608FStringExp : FBuiltInFunctionCall ::= Value:FExp
     1609                                      [MinimumLength:FExp]
     1610                                      [LeftJustified:FExp]
     1611                                      [SignificantDigits:FExp]
     1612                                      [Format:FExp]
     1613                                      /[CFormat:FExp]/;
    16091614
    16101615/**
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/test/modelica/EvaluationTests.mo

    r13503 r13702  
    46824682
    46834683model StringConvertWithParam1
     4684    /* TODO: a constant with a binding expression depending on parameters isn't really allowed,
     4685             but we don't check it - need to find a better way to test this when that is fixed
     4686             perhaps a string param that becomes structural?
     4687     */
    46844688    parameter Integer len = 8;
    46854689    parameter Boolean left = false;
     
    46944698        flatModel="
    46954699fclass EvaluationTests.StringConvert.StringConvertWithParam1
    4696  structural parameter Integer len = 8 /* 8 */;
    4697  structural parameter Boolean left = false /* false */;
    4698  structural parameter Integer dig = 4 /* 4 */;
     4700 parameter Integer len = 8 /* 8 */;
     4701 parameter Boolean left = false /* false */;
     4702 parameter Integer dig = 4 /* 4 */;
    46994703 constant Real x = 1.23456789;
    47004704 constant String s = \"   1.23\";
     
    47054709
    47064710model StringConvertWithParam2
     4711    /* TODO: a constant with a binding expression depending on parameters isn't really allowed,
     4712             but we don't check it - need to find a better way to test this when that is fixed
     4713             perhaps a string param that becomes structural?
     4714     */
    47074715    parameter String fmtSize = "10.4";
    47084716    constant Real x = 1.23456789;
     
    47154723        flatModel="
    47164724fclass EvaluationTests.StringConvert.StringConvertWithParam2
    4717  parameter String fmtSize = \"10.4\" /* \"10.4\" */;
     4725 structural parameter String fmtSize = \"10.4\" /* \"10.4\" */;
    47184726 constant Real x = 1.23456789;
    47194727 constant String s = \"1.2346E+00\";
     
    48834891
    48844892model StringRealformatSpecifier_d
    4885     constant Real x = 1.23456789;
     4893    constant Real x = 1234.56789;
    48864894    constant String s = String(x, format = "3d");
    48874895
    48884896annotation(__JModelica(UnitTesting(tests={
    4889       ErrorTestCase(
    4890             name="StringRealformatSpecifier_d",
    4891             description="String() operator, Real, format using d specifier",
    4892             errorMessage="
    4893 Error at line 3, column 25, in file '...':
    4894   Could not evaluate binding expression for constant 's': 'String(x, \"3d\")'
    4895     Cannot format the resulting value. The format '%3d' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     4897    FlatteningTestCase(
     4898        name="StringRealformatSpecifier_d",
     4899        description="String() operator, Real, format using d specifier",
     4900        flatModel="
     4901fclass EvaluationTests.StringConvert.StringRealformatSpecifier_d
     4902 constant Real x = 1234.56789;
     4903 constant String s = \"1234\";
     4904end EvaluationTests.StringConvert.StringRealformatSpecifier_d;
    48964905")})));
    48974906end StringRealformatSpecifier_d;
     
    49144923
    49154924model StringRealformatSpecifier_i
    4916     constant Real x = 1.23456789;
     4925    constant Real x = 1234.56789;
    49174926    constant String s = String(x, format = "3i");
    49184927
    49194928annotation(__JModelica(UnitTesting(tests={
    4920     ErrorTestCase(
     4929    FlatteningTestCase(
    49214930        name="StringRealformatSpecifier_i",
    49224931        description="String() operator, Real, format using i specifier",
    4923         errorMessage="
    4924 Error at line 3, column 25, in file '...':
    4925   Could not evaluate binding expression for constant 's': 'String(x, \"3i\")'
    4926     Cannot format the resulting value. The format '%3i' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     4932        flatModel="
     4933fclass EvaluationTests.StringConvert.StringRealformatSpecifier_i
     4934 constant Real x = 1234.56789;
     4935 constant String s = \"1234\";
     4936end EvaluationTests.StringConvert.StringRealformatSpecifier_i;
    49274937")})));
    49284938end StringRealformatSpecifier_i;
     
    49454955
    49464956model StringRealformatSpecifier_o
    4947     constant Real x = 1.23456789;
     4957    constant Real x = 1234.56789;
    49484958    constant String s = String(x, format = "3o");
    49494959
    49504960annotation(__JModelica(UnitTesting(tests={
    4951     ErrorTestCase(
     4961    FlatteningTestCase(
    49524962        name="StringRealformatSpecifier_o",
    49534963        description="String() operator, Real, format using o specifier",
    4954         errorMessage="
    4955 Error at line 3, column 25, in file '...':
    4956   Could not evaluate binding expression for constant 's': 'String(x, \"3o\")'
    4957     Cannot format the resulting value. The format '%3o' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     4964        flatModel="
     4965fclass EvaluationTests.StringConvert.StringRealformatSpecifier_o
     4966 constant Real x = 1234.56789;
     4967 constant String s = \"2322\";
     4968end EvaluationTests.StringConvert.StringRealformatSpecifier_o;
    49584969")})));
    49594970end StringRealformatSpecifier_o;
     
    49764987
    49774988model StringRealformatSpecifier_x
    4978     constant Real x = 1.23456789;
     4989    constant Real x = 1234.56789;
    49794990    constant String s = String(x, format = "3x");
    49804991
    49814992annotation(__JModelica(UnitTesting(tests={
    4982     ErrorTestCase(
     4993    FlatteningTestCase(
    49834994        name="StringRealformatSpecifier_x",
    49844995        description="String() operator, Real, format using x specifier",
    4985         errorMessage="
    4986 Error at line 3, column 25, in file '...':
    4987   Could not evaluate binding expression for constant 's': 'String(x, \"3x\")'
    4988     Cannot format the resulting value. The format '%3x' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     4996        flatModel="
     4997fclass EvaluationTests.StringConvert.StringRealformatSpecifier_x
     4998 constant Real x = 1234.56789;
     4999 constant String s = \"4d2\";
     5000end EvaluationTests.StringConvert.StringRealformatSpecifier_x;
    49895001")})));
    49905002end StringRealformatSpecifier_x;
     
    50075019
    50085020model StringRealformatSpecifier_X
    5009     constant Real x = 1.23456789;
     5021    constant Real x = 1234.56789;
    50105022    constant String s = String(x, format = "3X");
    50115023
    50125024annotation(__JModelica(UnitTesting(tests={
    5013     ErrorTestCase(
     5025    FlatteningTestCase(
    50145026        name="StringRealformatSpecifier_X",
    50155027        description="String() operator, Real, format using X specifier",
    5016         errorMessage="
    5017 Error at line 3, column 25, in file '...':
    5018   Could not evaluate binding expression for constant 's': 'String(x, \"3X\")'
    5019     Cannot format the resulting value. The format '%3X' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     5028        flatModel="
     5029fclass EvaluationTests.StringConvert.StringRealformatSpecifier_X
     5030 constant Real x = 1234.56789;
     5031 constant String s = \"4D2\";
     5032end EvaluationTests.StringConvert.StringRealformatSpecifier_X;
    50205033")})));
    50215034end StringRealformatSpecifier_X;
     
    50385051
    50395052model StringRealformatSpecifier_u
    5040     constant Real x = 1.23456789;
     5053    constant Real x = -1234.56789;
    50415054    constant String s = String(x, format = "3u");
    50425055
    50435056annotation(__JModelica(UnitTesting(tests={
    5044     ErrorTestCase(
     5057    FlatteningTestCase(
    50455058        name="StringRealformatSpecifier_u",
    5046         description="String() operator, Real, format using u specifier",
    5047         errorMessage="
    5048 Error at line 3, column 25, in file '...':
    5049   Could not evaluate binding expression for constant 's': 'String(x, \"3u\")'
    5050     Cannot format the resulting value. The format '%3u' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
     5059        description="String() operator,  Real, format using u specifier",
     5060        flatModel="
     5061fclass EvaluationTests.StringConvert.StringRealformatSpecifier_u
     5062 constant Real x = -1234.56789;
     5063 constant String s = \"4294966061\";
     5064end EvaluationTests.StringConvert.StringRealformatSpecifier_u;
    50515065")})));
    50525066end StringRealformatSpecifier_u;
     
    50695083
    50705084model StringRealformatSpecifier_c
    5071     constant Real x = 1.23456789;
     5085    constant Real x = 123.456789;
    50725086    constant String s = String(x, format = "3c");
    50735087
    50745088annotation(__JModelica(UnitTesting(tests={
    5075     ErrorTestCase(
     5089    FlatteningTestCase(
    50765090        name="StringRealformatSpecifier_c",
    5077         description="String() operator, Real, format using c specifier",
    5078         errorMessage="
    5079 Error at line 3, column 25, in file '...':
    5080   Could not evaluate binding expression for constant 's': 'String(x, \"3c\")'
    5081     Cannot format the resulting value. The format '%3c' requires value of Integer type but Real value is provided. CValueReal (1.23456789)
    5082 ")})));
    5083 
     5091        description="String() operator,  Real, format using c specifier",
     5092        flatModel="
     5093fclass EvaluationTests.StringConvert.StringRealformatSpecifier_c
     5094 constant Real x = 123.456789;
     5095 constant String s = \"  {\";
     5096end EvaluationTests.StringConvert.StringRealformatSpecifier_c;
     5097")})));
    50845098end StringRealformatSpecifier_c;
    50855099
     
    51005114end StringIntegerformatSpecifier_c;
    51015115
    5102 model StringIncorrectformat
    5103     constant Integer x = 1234;
    5104     constant String s = String(x, format = "*.1.3c");
     5116
     5117model StringConvertInvalidFormat1
     5118    parameter Real x = 1.23456789;
     5119    parameter String s = String(x, format = "1.2.3g");
    51055120
    51065121annotation(__JModelica(UnitTesting(tests={
    51075122    ErrorTestCase(
    5108         name="StringIncorrectformat",
    5109         description="String() operator, Real, format using c specifier",
     5123        name="StringConvert_StringConvertInvalidFormat1",
     5124        description="String() operator, Real, bad format string",
    51105125        errorMessage="
    5111 Error at line 3, column 25, in file '...':
    5112   Could not evaluate binding expression for constant 's': 'String(x, \"*.1.3c\")'
    5113     Cannot format the resulting value. %*.1.3c is not a supported valid format stringCValueInteger (1234)
    5114 ")})));
    5115 end StringIncorrectformat;
     5126Error at line 3, column 26, in file '...', INVALID_FORMAT_STRING:
     5127  Failed to parse format string \"1.2.3g\".
     5128")})));
     5129end StringConvertInvalidFormat1;
     5130
     5131
     5132model StringConvertInvalidFormat2
     5133    parameter Integer x = 1;
     5134    parameter String s = String(x, format = "ld");
     5135
     5136annotation(__JModelica(UnitTesting(tests={
     5137    ErrorTestCase(
     5138        name="StringConvert_StringConvertInvalidFormat2",
     5139        description="String() operator, Real, bad format string (different internal exception)",
     5140        errorMessage="
     5141Error at line 3, column 26, in file '...', INVALID_FORMAT_STRING:
     5142  Length modifiers are not allowed in format strings, but \"ld\" has length modifier \"l\".
     5143")})));
     5144end StringConvertInvalidFormat2;
    51165145
    51175146end StringConvert;
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/jastadd/errorcheck/ComplianceCheck.jadd

    r11639 r13702  
    283283
    284284    public static final SimpleProblemProducer ASTNode.UNSUPPORTED_NON_FIXED_STRING_ARGUMENT =
    285             new SimpleErrorProducer("UNSUPPORTED_NON_FIXED_STRING_ARGUMENT", ProblemKind.COMPLIANCE, "%s with higher than parameter variability is not supported");
     285            new SimpleErrorProducer("UNSUPPORTED_NON_FIXED_STRING_ARGUMENT", ProblemKind.COMPLIANCE,
     286                    "Argument %s of String operator is only supported as parameter expression.");
    286287
    287288    public void FStringExp.complianceCheck(ErrorCheckType checkType) {
    288289        super.complianceCheck(checkType);
    289         boolean func = inFunction();
    290         if (!func && hasMinimumLength()) {
    291             getMinimumLength().markAsStructuralParameter(checkType);
    292             if (!getMinimumLength().variability().parameterOrLess())
    293                 UNSUPPORTED_NON_FIXED_STRING_ARGUMENT.invoke(getMinimumLength(), "minimumLength");
    294         }
    295         if (!func && hasLeftJustified()) {
    296             getLeftJustified().markAsStructuralParameter(checkType);
    297            if (!getLeftJustified().variability().parameterOrLess())
    298                UNSUPPORTED_NON_FIXED_STRING_ARGUMENT.invoke(getLeftJustified(), "leftJustified");
    299         }
    300         if (!func && hasSignificantDigits()) {
    301             getSignificantDigits().markAsStructuralParameter(checkType);
    302             if (!getSignificantDigits().variability().parameterOrLess())
    303                 UNSUPPORTED_NON_FIXED_STRING_ARGUMENT.invoke(getSignificantDigits(), "significantDigits");
    304        }
     290        if (hasFormat()) {
     291            getFormat().markAsStructuralParameter(checkType);
     292            // TODO: need to cover functions as well
     293            if (!getFormat().variability().parameterOrLess())
     294                UNSUPPORTED_NON_FIXED_STRING_ARGUMENT.invoke(getFormat(), "format");
     295        }
    305296    }
    306297
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/jastadd/errorcheck/ContentsCheck.jadd

    r13103 r13702  
    389389            if (!ch.variability().parameterOrLess()) {
    390390                NON_PARAMETER_SAMPLE_ARGUMENTS.invoke(ch);
     391            }
     392        }
     393    }
     394   
     395    public static final SimpleErrorProducer ASTNode.INVALID_FORMAT_STRING =
     396            new SimpleErrorProducer("INVALID_FORMAT_STRING", ProblemKind.SEMANTIC, "%s");
     397
     398    public void FStringExp.contentCheck(ErrorCheckType checkType) {
     399        if (hasFormat()) {
     400            try {
     401                CFormatSpecifier format = formatSpecifier();
     402                if (!format.isValid()) {
     403                    INVALID_FORMAT_STRING.invoke(this, format.errorMessage());
     404                }
     405            } catch (ConstantEvaluationException e) {
     406                // If we can't evaluate it, don't do a static error check of it.
    391407            }
    392408        }
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/values/ConstantEvaluationException.java

    r9590 r13702  
    1414    public ConstantEvaluationException() {
    1515        super("Unspecified constant evaluation failure");
     16        this.val = null;
     17    }
     18
     19    public ConstantEvaluationException(String msg) {
     20        super(msg);
     21        this.val = null;
     22    }
     23
     24    public ConstantEvaluationException(String msg, Throwable cause) {
     25        super(msg, cause);
    1626        this.val = null;
    1727    }
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo

    r11639 r13702  
    527527
    528528model StringOperator1
     529    function f
     530        input Real x;
     531        input String f;
     532        output String o;
     533    algorithm
     534        o := String(x, format=f);
     535    end f;
     536   
    529537    Integer len = if time < 0 then 4 else 3;
    530538    Integer digits = if time < 0 then 5 else 2;
     539    String s = f(time, "g");
    531540equation
    532541    assert(time>2.0, String(time, significantDigits=digits, minimumLength=len, leftJustified=time<1));
     542    assert(time>2.0, String(time, format=String(len)+"."+String(digits)+"f"));
    533543    annotation(__JModelica(UnitTesting(tests={
    534544        ComplianceErrorTestCase(
    535545            name="StringOperator1",
    536             description="Test compliance warnings for non fixed string operator arguments (significantDigits, minimumLength, leftJustified)",
    537             errorMessage="
    538 3 errors found:
    539 
    540 Compliance error at line 5, column 53, in file 'Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo', UNSUPPORTED_NON_FIXED_STRING_ARGUMENT:
    541   significantDigits with higher than parameter variability is not supported
    542 
    543 Compliance error at line 5, column 75, in file 'Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo', UNSUPPORTED_NON_FIXED_STRING_ARGUMENT:
    544   minimumLength with higher than parameter variability is not supported
    545 
    546 Compliance error at line 5, column 94, in file 'Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo', UNSUPPORTED_NON_FIXED_STRING_ARGUMENT:
    547   leftJustified with higher than parameter variability is not supported
    548 ")})));
     546            description="Test compliance warnings for non fixed string operator format argument",
     547            errorMessage="
     5482 errors found:
     549 
     550Compliance error at line 7, column 31, in file 'Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo', UNSUPPORTED_NON_FIXED_STRING_ARGUMENT:
     551 Argument format of String operator is only supported as parameter expression.
     552 
     553Compliance error at line 15, column 42, in file 'Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo', UNSUPPORTED_NON_FIXED_STRING_ARGUMENT:
     554 Argument format of String operator is only supported as parameter expression.
     555   ")})));
    549556end StringOperator1;
    550557
Note: See TracChangeset for help on using the changeset viewer.