diff options
author | 2015-11-09 16:06:49 +0000 | |
---|---|---|
committer | 2015-11-10 10:23:05 +0000 | |
commit | 1bf1c970cad8bd2f1b7b42b1038b87e10d6a5428 (patch) | |
tree | af321600847460c068ec315938d41e0c7a110017 /src | |
parent | 3ef1eea7b84841bb696ad6341b2503804fa6562c (diff) |
Compile conditional statement and expressions.
--
MOS_MIGRATED_REVID=107385205
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java | 40 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java | 54 |
2 files changed, 93 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java index 652baa6555..be83c3144c 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/ConditionalExpression.java @@ -11,9 +11,22 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - package com.google.devtools.build.lib.syntax; +import static com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils.append; + +import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils; +import com.google.devtools.build.lib.syntax.compiler.DebugInfo; +import com.google.devtools.build.lib.syntax.compiler.Jump; +import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison; +import com.google.devtools.build.lib.syntax.compiler.LabelAdder; +import com.google.devtools.build.lib.syntax.compiler.VariableScope; + +import net.bytebuddy.implementation.bytecode.ByteCodeAppender; + +import java.util.ArrayList; +import java.util.List; + /** * Syntax node for an if/else expression. */ @@ -67,4 +80,29 @@ public final class ConditionalExpression extends Expression { thenCase.validate(env); elseCase.validate(env); } + + @Override + ByteCodeAppender compile(VariableScope scope, DebugInfo debugInfo) throws EvalException { + List<ByteCodeAppender> code = new ArrayList<>(); + LabelAdder afterLabel = new LabelAdder(); + LabelAdder elseLabel = new LabelAdder(); + // compile condition and convert to boolean + code.add(condition.compile(scope, debugInfo)); + append( + code, + EvalUtils.toBoolean, + // jump to else block if false + Jump.ifIntOperandToZero(PrimitiveComparison.EQUAL).to(elseLabel)); + // otherwise evaluate the expression for "then" and jump to end + code.add(thenCase.compile(scope, debugInfo)); + append( + code, + Jump.to(afterLabel), + // add label for "else" and evaluate the expression + elseLabel); + code.add(elseCase.compile(scope, debugInfo)); + append(code, afterLabel); + + return ByteCodeUtils.compoundAppender(code); + } } diff --git a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java index ffe29479bd..a40a4daf37 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/IfStatement.java @@ -13,9 +13,22 @@ // limitations under the License. package com.google.devtools.build.lib.syntax; +import static com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils.append; + +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils; +import com.google.devtools.build.lib.syntax.compiler.DebugInfo; +import com.google.devtools.build.lib.syntax.compiler.Jump; +import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison; +import com.google.devtools.build.lib.syntax.compiler.LabelAdder; +import com.google.devtools.build.lib.syntax.compiler.LoopLabels; +import com.google.devtools.build.lib.syntax.compiler.VariableScope; + +import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import java.util.ArrayList; import java.util.List; /** @@ -66,6 +79,17 @@ public final class IfStatement extends Statement { condition.validate(env); validateStmts(env, stmts); } + + @Override + ByteCodeAppender compile( + VariableScope scope, Optional<LoopLabels> loopLabels, DebugInfo debugInfo) + throws EvalException { + List<ByteCodeAppender> code = new ArrayList<>(); + for (Statement statement : stmts) { + code.add(statement.compile(scope, loopLabels, debugInfo)); + } + return ByteCodeUtils.compoundAppender(code); + } } private final ImmutableList<ConditionalStatements> thenBlocks; @@ -132,4 +156,34 @@ public final class IfStatement extends Statement { } env.finishTemporarilyDisableReadonlyCheckBranch(); } + + @Override + ByteCodeAppender compile( + VariableScope scope, Optional<LoopLabels> loopLabels, DebugInfo debugInfo) + throws EvalException { + List<ByteCodeAppender> code = new ArrayList<>(); + LabelAdder after = new LabelAdder(); + LabelAdder nextConditionalOrElse; + for (ConditionalStatements statement : thenBlocks) { + nextConditionalOrElse = new LabelAdder(); + // compile condition and convert to boolean + code.add(statement.getCondition().compile(scope, debugInfo)); + append( + code, + EvalUtils.toBoolean, + // jump to next conditional/else block if false + Jump.ifIntOperandToZero(PrimitiveComparison.EQUAL).to(nextConditionalOrElse)); + // otherwise execute the body and jump to end + code.add(statement.compile(scope, loopLabels, debugInfo)); + append(code, Jump.to(after)); + // add label for next conditional or the else block (which may be empty, but no matter) + append(code, nextConditionalOrElse); + } + for (Statement statement : elseBlock) { + code.add(statement.compile(scope, loopLabels, debugInfo)); + } + append(code, after); + + return ByteCodeUtils.compoundAppender(code); + } } |