Changeset 13861


Ignore:
Timestamp:
Oct 25, 2019 2:39:49 PM (4 weeks ago)
Author:
Jesper Mattsson
Message:

Allowed format strings including the initial % (with a warning), and added unit tests of CFormatSpecifier. (#5835)

Location:
branches/dev-mj-5835/Compiler
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • branches/dev-mj-5835/Compiler/ModelicaCBackEnd/test/modelica/CCodeGenTests.mo

    r13714 r13861  
    1601916019        input Integer i;
    1602016020        input Boolean b;
    16021         input String fmt;
    1602216021        output Real y;
    1602316022        String s;
     
    1602916028        + String(x, significantDigits=i, leftJustified=b)
    1603016029        + String(x)
    16031         + String(x, format=fmt)
    1603216030       
    1603316031        + String(i, minimumLength=2, leftJustified=b)
    1603416032        + String(i, minimumLength=i, leftJustified=true)
    1603516033        + String(i, minimumLength=i, leftJustified=b)
    16036         + String(i, format=fmt)
    1603716034       
    1603816035        + String(b, minimumLength=2, leftJustified=b)
     
    1604116038    end f;
    1604216039   
    16043     Real y = f(-time, 3, true, "g");
     16040    Real y = f(-time, 3, true);
    1604416041
    1604516042annotation(__JModelica(UnitTesting(tests={
     
    1605116048        template="$C_functions$",
    1605216049        generatedCode="
    16053 void func_CCodeGenTests_StringOperations9_f_def0(jmi_real_t x_v, jmi_real_t i_v, jmi_real_t b_v, jmi_string_t fmt_v, jmi_real_t* y_o) {
     16050void func_CCodeGenTests_StringOperations9_f_def0(jmi_real_t x_v, jmi_real_t i_v, jmi_real_t b_v, jmi_real_t* y_o) {
    1605416051    JMI_DYNAMIC_INIT()
    1605516052    JMI_DEF(REA, y_v)
    1605616053    JMI_DEF(STR, s_v)
    1605716054    JMI_DEF_STR_DYNA(tmp_1)
    16058     JMI_DEF_STR_DYNA(tmp_2)
    16059     JMI_DEF_STR_DYNA(tmp_3)
    1606016055    JMI_INI(STR, s_v)
    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)
     16056    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 + jmi_max(10, 2.0) + jmi_max(10, i_v) + jmi_max(10, i_v) + jmi_max(5, 2.0) + jmi_max(5, i_v) + jmi_max(5, i_v))
     16057    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);
     16058    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);
     16059    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);
     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) i_v, x_v);
     16061    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);
     16062    snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), \"%-.*g\", (int) 6, x_v);
     16063    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);
     16064    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);
     16065    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);
     16066    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\"));
     16067    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\"));
     16068    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\"));
     16069    JMI_ASG(STR, s_v, tmp_1)
    1608316070    JMI_RET(GEN, y_o, y_v)
    1608416071    JMI_DYNAMIC_FREE()
     
    1608616073}
    1608716074
    16088 jmi_real_t func_CCodeGenTests_StringOperations9_f_exp0(jmi_real_t x_v, jmi_real_t i_v, jmi_real_t b_v, jmi_string_t fmt_v) {
     16075jmi_real_t func_CCodeGenTests_StringOperations9_f_exp0(jmi_real_t x_v, jmi_real_t i_v, jmi_real_t b_v) {
    1608916076    JMI_DEF(REA, y_v)
    16090     func_CCodeGenTests_StringOperations9_f_def0(x_v, i_v, b_v, fmt_v, &y_v);
     16077    func_CCodeGenTests_StringOperations9_f_def0(x_v, i_v, b_v, &y_v);
    1609116078    return y_v;
    1609216079}
     
    1631216299")})));
    1631316300end StringOperations12;
     16301
     16302
     16303model StringOperations13
     16304    function f
     16305        input Real x;
     16306        output Real y;
     16307    protected
     16308        String s;
     16309    algorithm
     16310        s := String(x, format="%g");
     16311        y := x + .5;
     16312    end f;
     16313   
     16314    Real y = f(time);
     16315
     16316annotation(__JModelica(UnitTesting(tests={
     16317    CCodeGenTestCase(
     16318        name="StringOperations13",
     16319        description="Check that we handle case where initial '%' of format specifier is included in format argument of String()",
     16320        template="$C_functions$",
     16321        generatedCode="
     16322void func_CCodeGenTests_StringOperations13_f_def0(jmi_real_t x_v, jmi_real_t* y_o) {
     16323    JMI_DYNAMIC_INIT()
     16324    JMI_DEF(REA, y_v)
     16325    JMI_DEF(STR, s_v)
     16326    JMI_DEF_STR_STAT(tmp_1, 16)
     16327    JMI_INI(STR, s_v)
     16328    JMI_INI_STR_STAT(tmp_1)
     16329    snprintf(JMI_STR_END(tmp_1), JMI_STR_LEFT(tmp_1), \"%g\", x_v);
     16330    JMI_ASG(STR, s_v, tmp_1)
     16331    y_v = x_v + 0.5;
     16332    JMI_RET(GEN, y_o, y_v)
     16333    JMI_DYNAMIC_FREE()
     16334    return;
     16335}
     16336
     16337jmi_real_t func_CCodeGenTests_StringOperations13_f_exp0(jmi_real_t x_v) {
     16338    JMI_DEF(REA, y_v)
     16339    func_CCodeGenTests_StringOperations13_f_def0(x_v, &y_v);
     16340    return y_v;
     16341}
     16342
     16343")})));
     16344end StringOperations13;
    1631416345
    1631516346package TestTerminate
  • branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/FlatAPI/FlatAPI.jrag

    r13702 r13861  
    44734473        // TODO: To save memory, this could be solved in the C code generation instead.
    44744474        if (hasFormat()) {
     4475            boolean hasPercent = formatSpecifier().initialPercent;
    44754476            FExp fmt = getFormat();
    4476             FExp exp = new FStringAddExp(new FStringLitExp("%"), fmt.treeCopy());
     4477            FExp exp = fmt.treeCopy();
     4478            if (!formatSpecifier().initialPercent) {
     4479                exp = new FStringAddExp(new FStringLitExp("%"), exp);
     4480            }
    44774481            if (fmt.variability().fixedParameterOrLess()) {
    44784482                try {
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/jastadd/errorcheck/ContentsCheck.jadd

    r13702 r13861  
    2222import org.jmodelica.common.URIResolver;
    2323import org.jmodelica.common.URIResolver.URIException;
     24import org.jmodelica.util.problemHandling.SimpleErrorOrWarningProducer;
    2425
    2526aspect ContentCheck {
     
    393394    }
    394395   
    395     public static final SimpleErrorProducer ASTNode.INVALID_FORMAT_STRING =
    396             new SimpleErrorProducer("INVALID_FORMAT_STRING", ProblemKind.SEMANTIC, "%s");
     396    public static final SimpleErrorOrWarningProducer ASTNode.INVALID_FORMAT_STRING =
     397            new SimpleErrorOrWarningProducer("INVALID_FORMAT_STRING", ProblemKind.SEMANTIC, "%s");
    397398
    398399    public void FStringExp.contentCheck(ErrorCheckType checkType) {
     
    400401            try {
    401402                CFormatSpecifier format = formatSpecifier();
    402                 if (!format.isValid()) {
    403                     INVALID_FORMAT_STRING.invoke(this, format.errorMessage());
     403                if (format.hasProblem()) {
     404                    INVALID_FORMAT_STRING.invoke(this, format.hasError(), format.errorMessage());
    404405                }
    405406            } catch (ConstantEvaluationException e) {
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/problemHandling/SimpleErrorProducer.java

    r9003 r13861  
    66/**
    77 * If you have a error message which only consists of a string and format
    8  * arguments, then this is the right class for you. Simple create a static
     8 * arguments, then this is the right class for you. Simply create a static
    99 * final field instantiating this class and then invoke the error as needed!
    1010 */
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/problemHandling/SimpleWarningProducer.java

    r9003 r13861  
    55
    66/**
    7  * Convenient class which takes a string message on construction, an
     7 * Convenience class which takes a string message on construction, an
    88 * optional list of format arguments when invoked and produces a warning.
    99 */
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/values/CFormatSpecifier.java

    r13702 r13861  
    7272
    7373    private static final String SYNTAX_TAG        = "(%|)";
    74     private static final String SYNTAX_FLAGS      = "([-+ 0#]|)";
     74    private static final String SYNTAX_FLAGS      = "([-+ 0#]*)";
    7575    private static final String SYNTAX_WIDTH      = "([1-9][0-9]*)?";
    7676    private static final String SYNTAX_PRECISION  = "(\\.([1-9][0-9]*))?";
     
    171171
    172172    public boolean isValid() {
    173         return  !parsingFailed &&
    174                 !initialPercent &&
    175                 length.isEmpty();
     173        return !parsingFailed &&
     174               length.isEmpty();
     175    }
     176
     177    public boolean hasProblem() {
     178        return hasError() || hasWarning();
     179    }
     180
     181    public boolean hasError() {
     182        return !isValid();
     183    }
     184
     185    public boolean hasWarning() {
     186        return initialPercent;
    176187    }
    177188
  • branches/dev-mj-5835/Compiler/ModelicaFrontEnd/test/modelica/ComplianceTests.mo

    r13714 r13861  
    567567
    568568
     569model StringOperator2
     570    String s = String(time, format="%f");
     571
     572annotation(__JModelica(UnitTesting(tests={
     573    WarningTestCase(
     574        name="StringOperator2",
     575        description="Test warning for supplying the initial % of format specifier",
     576        errorMessage="
     577
     578
     579Warning at line 2, column 16, in file '...', INVALID_FORMAT_STRING:
     580  The format string argument should not include the initial '%': \"%f\".
     581")})));
     582end StringOperator2;
     583
    569584
    570585package UnknownArraySizes
Note: See TracChangeset for help on using the changeset viewer.