• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 203

18 Oct 2023 02:20PM UTC coverage: 63.758% (+0.3%) from 63.447%
203

push

circleci

web-flow
Update deps, improve performance, JHCR fixes (#1080)

- update dependencies
- update stdlib verison for unit tests
- only apply nullsetting when `-opt` is enabled to save some build time for testing
- minor performance improvements
- make build deterministic
- apply build map config before compilation
- hot code reload now more reliable

17246 of 27049 relevant lines covered (63.76%)

0.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/NullSetter.java
1
package de.peeeq.wurstscript.translation.imoptimizer;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Sets;
5
import de.peeeq.wurstscript.jassIm.*;
6
import de.peeeq.wurstscript.translation.imtranslation.ImHelper;
7
import de.peeeq.wurstscript.translation.imtranslation.ImTranslator;
8

9
import java.util.List;
10
import java.util.Set;
11

12
/**
13
 * sets local handle variables to null at every return statement
14
 */
15
public class NullSetter {
16

17

18
    private ImProg prog;
19
    private ImTranslator translator;
20

21
    // the types which are not set to null
22
    private Set<String> primitiveTypes = Sets.newHashSet("boolean", "integer", "string", "code", "real");
×
23

24
    public NullSetter(ImTranslator translator) {
×
25
        this.translator = translator;
×
26
        this.prog = translator.getImProg();
×
27
    }
×
28

29
    public void optimize() {
30
        prog.flatten(translator);
×
31
        for (ImFunction f : ImHelper.calculateFunctionsOfProg(prog)) {
×
32
            optimizeFunc(f);
×
33
        }
×
34

35
    }
×
36

37
    private void optimizeFunc(final ImFunction f) {
38
        if (f.isBj() || f.isNative() || f.isCompiletime() || f.isExtern()) {
×
39
            return;
×
40
        }
41
        final List<ImVar> handleVars = Lists.newArrayList();
×
42
        for (ImVar local : f.getLocals()) {
×
43
            if (isHandleType(local.getType())) {
×
44
                handleVars.add(local);
×
45
            }
46
        }
×
47
        if (handleVars.isEmpty()) {
×
48
            // functions without handle vars can be skipped
49
            return;
×
50
        }
51
        final List<ImStmt> nullSetStmts = Lists.newArrayList();
×
52
        final de.peeeq.wurstscript.ast.Element trace = f.getTrace();
×
53
        for (ImVar local : handleVars) {
×
54
            nullSetStmts.add(JassIm.ImSet(trace, JassIm.ImVarAccess(local), JassIm.ImNull(local.getType())));
×
55
        }
×
56
        boolean returns = optimizeChildren(f, handleVars, nullSetStmts, trace, f.getBody());
×
57

58
        if (!returns) {
×
59
            // add null set statements if not alreay returned ...
60
            addNullSetStmts(f.getBody(), f.getBody().size(), nullSetStmts);
×
61
        }
62
    }
×
63

64
    /**
65
     * adds nullSetStmts in front of every return statement
66
     * <p>
67
     * returns true if "parent" always returns
68
     *
69
     * @param f
70
     * @param handleVars
71
     * @param nullSetStmts
72
     * @param trace
73
     * @param parent
74
     * @return
75
     */
76
    private boolean optimizeChildren(final ImFunction f,
77
                                     final List<ImVar> handleVars, final List<ImStmt> nullSetStmts,
78
                                     final de.peeeq.wurstscript.ast.Element trace, Element parent) {
79
        for (int i = 0; i < parent.size(); i++) {
×
80
            Element elem = parent.get(i);
×
81
            if (elem instanceof ImReturn) {
×
82
                handleReturnStmt(f, handleVars, nullSetStmts, trace, (ImReturn) elem);
×
83
                return true;
×
84
            } else if (elem instanceof ImIf) {
×
85
                ImIf imIf = (ImIf) elem;
×
86
                boolean returnsThen = optimizeChildren(f, handleVars, nullSetStmts, trace, imIf.getThenBlock());
×
87
                boolean returnsElse = optimizeChildren(f, handleVars, nullSetStmts, trace, imIf.getElseBlock());
×
88
                if (returnsThen && returnsElse) {
×
89
                    return true;
×
90
                }
91
            } else if (elem instanceof ImLoop) {
×
92
                optimizeChildren(f, handleVars, nullSetStmts, trace, elem);
×
93
                // simplifying assumption: loops never return always
94
            } else {
95
                // visit children
96
                boolean returns = optimizeChildren(f, handleVars, nullSetStmts, trace, elem);
×
97
                if (returns) {
×
98
                    return true;
×
99
                }
100
            }
101
        }
102
        return false;
×
103
    }
104

105
    private void handleReturnStmt(final ImFunction f,
106
                                  final List<ImVar> handleVars, final List<ImStmt> nullSetStmts,
107
                                  final de.peeeq.wurstscript.ast.Element trace, ImReturn imReturn) {
108
        ImStmts parent2 = (ImStmts) imReturn.getParent();
×
109
        int parentIndex = parent2.indexOf(imReturn);
×
110
        if (imReturn.getReturnValue() instanceof ImExpr) { // returns some value
×
111
            ImExpr returnExpr = (ImExpr) imReturn.getReturnValue();
×
112

113
            addNullSetStmts(parent2, parentIndex, nullSetStmts);
×
114

115
            if (exprContainsVar(returnExpr, handleVars)) {
×
116
                // if the returnExpr contains some handleVar, we have to add a temporary var
117

118
                ImVar tempReturn = JassIm.ImVar(imReturn.attrTrace(), returnExpr.attrTyp(), f.getName() + "tempReturn", false);
×
119
                if (isHandleType(returnExpr.attrTyp())) {
×
120
                    // use global variables for handle types
121
                    prog.getGlobals().add(tempReturn);
×
122
                } else {
123
                    // local variables for other types
124
                    f.getLocals().add(tempReturn);
×
125
                }
126

127
                imReturn.setReturnValue(JassIm.ImVarAccess(tempReturn));
×
128
                parent2.add(parentIndex, JassIm.ImSet(trace, JassIm.ImVarAccess(tempReturn), returnExpr));
×
129
            }
130

131
        } else { // normal return
×
132

133
            addNullSetStmts(parent2, parentIndex, nullSetStmts);
×
134
        }
135
    }
×
136

137
    private boolean exprContainsVar(ImExpr returnExpr, final List<ImVar> handleVars) {
138
        final boolean[] result = {false};
×
139
        returnExpr.accept(new ImExpr.DefaultVisitor() {
×
140
            @Override
141
            public void visit(ImVarAccess e) {
142
                super.visit(e);
×
143
                if (handleVars.contains(e.getVar())) {
×
144
                    result[0] = true;
×
145
                }
146
            }
×
147

148
        });
149
        return result[0];
×
150
    }
151

152
    private void addNullSetStmts(ImStmts parent, int parentIndex,
153
                                 List<ImStmt> nullSetStmts) {
154
        List<ImStmt> nullSetStmtsCopy = Lists.newArrayListWithCapacity(nullSetStmts.size());
×
155
        for (ImStmt s : nullSetStmts) {
×
156
            nullSetStmtsCopy.add((ImStmt) s.copy());
×
157
        }
×
158
        parent.addAll(parentIndex, nullSetStmtsCopy);
×
159
    }
×
160

161
    private boolean isHandleType(ImType type) {
162
        if (type instanceof ImSimpleType) {
×
163
            ImSimpleType imSimpleType = (ImSimpleType) type;
×
164
            return !primitiveTypes.contains(imSimpleType.getTypename());
×
165
        }
166
        return false;
×
167
    }
168

169

170
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc