Skip to content

Commit 1b52836

Browse files
committed
fix FIŘ tests + pre-commit hook
TODO: record promise forces in interpreter
1 parent e241c85 commit 1b52836

44 files changed

Lines changed: 978 additions & 1082 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/pre-commit.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
SERVER_DIR="server"
44
MVN="mvn -f $SERVER_DIR"
55

6-
staged_files=$(git diff --staged --name-only -- $SERVER_DIR)
7-
everything_staged=$(git diff --name-only -- $SERVER_DIR)
6+
staged_files=$(git diff --staged --name-only --diff-filter=d -- $SERVER_DIR)
7+
everything_staged=$(git diff --name-only --diff-filter=d -- $SERVER_DIR)
88
# `partially_staged` from https://github.com/evilmartians/lefthook/issues/140#issuecomment-1012967850
99
partially_staged=$(comm -12 <(echo "$everything_staged" | sort) <(echo "$staged_files" | sort))
1010
format_only_staged=-DspotlessFiles="$(echo "$staged_files" | sed 's/^/.*/' | paste -sd ',' -)"

client/rsh/src/bc2c/runtime.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ Rsh_Math1Fun R_MATH1_EXT_FUNS[] = {X_MATH1_EXT_OPS};
2424
SEXP NOT_OP;
2525
SEXP LOG_OP;
2626

27-
#include "../common2c/runtime_impl.h"
27+
#include "runtime_impl.h"

client/rsh/src/fir2c/runtime.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ void Fir_dbg_signature(Fir_Signature signature) {
10981098
fprintf(stderr, "\n");
10991099
}
11001100

1101-
DEFINE_INTRINSIC(SEXP, checkFun, value_fx_none_ret_value, SEXP value) {
1101+
DEFINE_INTRINSIC(SEXP, checkFun, value_fx_impure_ret_value, SEXP value) {
11021102
if (TYPEOF(value) != CLOSXP && TYPEOF(value) != BUILTINSXP &&
11031103
TYPEOF(value) != SPECIALSXP) {
11041104
Rf_error("attempt to apply non-function");
@@ -1107,7 +1107,7 @@ DEFINE_INTRINSIC(SEXP, checkFun, value_fx_none_ret_value, SEXP value) {
11071107
return R_NilValue;
11081108
}
11091109

1110-
DEFINE_INTRINSIC(SEXP, checkMissing, value_fx_none_ret_value, SEXP value) {
1110+
DEFINE_INTRINSIC(SEXP, checkMissing, value_fx_impure_ret_value, SEXP value) {
11111111
if (value == R_MissingArg) {
11121112
Rf_error("argument is missing, with no default");
11131113
}

client/rsh/src/fir2c/runtime.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ void Fir_dbg_signature(Fir_Signature signature);
188188

189189
#pragma clang diagnostic pop
190190

191-
DEFINE_INTRINSIC(SEXP, checkFun, value_fx_none_ret_value, SEXP value);
192-
DEFINE_INTRINSIC(SEXP, checkMissing, value_fx_none_ret_value, SEXP value);
191+
DEFINE_INTRINSIC(SEXP, checkFun, value_fx_impure_ret_value, SEXP value);
192+
DEFINE_INTRINSIC(SEXP, checkMissing, value_fx_impure_ret_value, SEXP value);
193193
DEFINE_INTRINSIC(SEXP, toForSeq, value_fx_none_ret_value, SEXP value);
194194
DEFINE_INTRINSIC(SEXP, toForSeq, vec_logical_fx_none_ret_vec_logical, SEXP value);
195195
DEFINE_INTRINSIC(SEXP, toForSeq, vec_int_fx_none_ret_vec_int, SEXP value);
@@ -412,11 +412,6 @@ DEFINE_OVERRIDDEN_BUILTIN(bool, is_u2echaracter, value_fx_none_ret_bool, SEXP va
412412
DEFINE_OVERRIDDEN_BUILTIN(bool, is_u2eobject, value_fx_none_ret_bool, SEXP value);
413413
DEFINE_OVERRIDDEN_BUILTIN(bool, is_u2esymbol, value_fx_none_ret_bool, SEXP value);
414414

415-
// Stubs for BC->C tests
416-
SEXP Rsh_initialize_runtime(void) { return R_NilValue; }
417-
SEXP Rsh_pc_get(void) { return R_NilValue; }
418-
SEXP Rsh_pc_reset(void) { return R_NilValue; }
419-
420415
#ifdef __cplusplus
421416
}
422417
#endif

server/src/main/java/org/prlprg/fir/analyze/Analyses.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.HashMap;
99
import java.util.Map;
1010
import java.util.NoSuchElementException;
11+
import java.util.Objects;
1112
import java.util.Set;
1213
import java.util.function.Function;
1314
import java.util.stream.Stream;
@@ -32,7 +33,7 @@ public class Analyses {
3233
private final AnalysisTypeMap<Analysis> abstractionAnalysisTypes;
3334
private final AnalysisTypeMap<CfgAnalysis> cfgAnalysisTypes;
3435

35-
private final Analysis[] abstractionAnalyses;
36+
private final @Nullable Analysis[] abstractionAnalyses;
3637
private final Map<CFG, CfgAnalysis[]> cfgAnalyses = new HashMap<>();
3738

3839
public Analyses(Abstraction target, Class<?>... analysisClasses) {
@@ -48,13 +49,6 @@ public Analyses(Abstraction target, AnalysisTypes analysisTypes) {
4849
abstractionAnalyses = new Analysis[abstractionAnalysisTypes.size()];
4950
}
5051

51-
/// Run all abstraction analyses.
52-
public void forceAbstractionAnalyses() {
53-
for (var analysisClass : abstractionAnalysisTypes.inherent) {
54-
get(analysisClass);
55-
}
56-
}
57-
5852
/// Clear all analyses so they must be recomputed.
5953
public void evict() {
6054
Arrays.fill(abstractionAnalyses, null);
@@ -82,7 +76,7 @@ private <T extends Analysis> T get(Class<T> analysisType, boolean allowDependenc
8276

8377
// Cast is safe because forall `T`,
8478
// `analysisTypes.get(T.class).analysisConstructor.newInstance(...) instanceof T`.
85-
return (T) abstractionAnalyses[info.index];
79+
return (T) Objects.requireNonNull(abstractionAnalyses[info.index]);
8680
}
8781

8882
/// @throws NoSuchElementException If `cfg` isn't in the `Abstraction` provided to the

server/src/main/java/org/prlprg/fir/analyze/resolve/OriginAnalysis.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,12 +462,16 @@ public State copy() {
462462

463463
@Override
464464
public void merge(State other) {
465-
// Merge origins = keep only those that are present in both and equal
466-
mergeOrigins(registerOrigins, other.registerOrigins);
467-
mergeOrigins(variableOrigins, other.variableOrigins);
465+
// Merge register origins = assume they're the same except for `null`s, unify
466+
// (because we may get origins of unreachable phis, for the workaround in `run(Jump)`).
467+
// Without support for the workaround, it would be the same as merging variable origins
468+
registerOrigins.putAll(other.registerOrigins);
469+
// Merge variable origins = keep only those that are present in both and equal
470+
mergeVariableOrigins(variableOrigins, other.variableOrigins);
468471
}
469472

470-
private static <T> void mergeOrigins(Map<T, Argument> origins, Map<T, Argument> otherOrigins) {
473+
private static <T> void mergeVariableOrigins(
474+
Map<T, Argument> origins, Map<T, Argument> otherOrigins) {
471475
for (var iterator = origins.entrySet().iterator(); iterator.hasNext(); ) {
472476
var entry = iterator.next();
473477
var variable = entry.getKey();

server/src/main/java/org/prlprg/fir/interpret/internal/Builtins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import org.prlprg.sexp.VecSXP;
3434

3535
/// Java implementations of GNU-R builtins for [InternalInterpreter] (specifically
36-
/// [InternalInterpreter#registerExternal(String, ExternalVersion)]).
36+
/// [InternalInterpreter#registerExternal(String, Signature, ExternalVersion)]).
3737
///
3838
/// Note that these are only behaviorally equivalent to GNU-R implementations in some common
3939
/// scenarios. They're not a complete substitute for GNU-R, but a way to test functions which
@@ -227,7 +227,7 @@ public static void registerBuiltins(InternalInterpreter interpreter) {
227227
"setVisible", sig(Type.ANY_VALUE_SEXP, Effects.NONE), Builtins::setVisible);
228228
interpreter.registerExternal(
229229
"checkMissing",
230-
sig(Type.ANY_VALUE_SEXP, Effects.NONE, Type.ANY_VALUE_SEXP),
230+
sig(Type.ANY_VALUE_SEXP, Effects.IMPURE, Type.ANY_VALUE_SEXP),
231231
Builtins::checkMissing);
232232
interpreter.registerExternal(
233233
"toForSeq",

server/src/main/java/org/prlprg/fir/opt/AbstractionOptimization.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import static org.prlprg.fir.opt.Cleanup.cleanup;
44

55
import java.util.List;
6+
import java.util.Optional;
7+
import org.jspecify.annotations.Nullable;
68
import org.prlprg.AppConfig;
79
import org.prlprg.fir.feedback.AbstractionFeedback;
810
import org.prlprg.fir.feedback.ModuleFeedback;
@@ -12,12 +14,13 @@
1214
/// An optimization that runs on an [Abstraction].
1315
public interface AbstractionOptimization extends Optimization {
1416
/// Returns `true` if it made progress.
15-
default boolean run(Function function, AbstractionFeedback feedback, Abstraction abstraction) {
16-
return function
17-
.owner()
17+
default boolean run(
18+
@Nullable Function function, AbstractionFeedback feedback, Abstraction abstraction) {
19+
return abstraction
20+
.module()
1821
.record(
1922
"AbstractionOptimization#run",
20-
List.of(this, function, feedback, abstraction),
23+
List.of(this, Optional.ofNullable(function), feedback, abstraction),
2124
() -> {
2225
var changed = runWithoutRecording(function, feedback, abstraction);
2326

@@ -45,5 +48,5 @@ default boolean runWithoutRecording(ModuleFeedback feedback, Function function)
4548

4649
/// Returns `true` if it made progress.
4750
boolean runWithoutRecording(
48-
Function function, AbstractionFeedback feedback, Abstraction abstraction);
51+
@Nullable Function function, AbstractionFeedback feedback, Abstraction abstraction);
4952
}

server/src/main/java/org/prlprg/fir/opt/Cleanup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public static boolean cleanup(Abstraction abstraction) {
7272

7373
@Override
7474
public boolean runWithoutRecording(
75-
Function function, AbstractionFeedback feedback, Abstraction abstraction) {
75+
@Nullable Function function, AbstractionFeedback feedback, Abstraction abstraction) {
7676
var opt = new OnAbstraction(abstraction);
7777
opt.run();
7878
return reportChanges && opt.changed;

server/src/main/java/org/prlprg/fir/opt/CreateBestVersion.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33
import static org.prlprg.fir.ir.abstraction.AbstractionCopier.copy;
44

55
import com.google.common.collect.ImmutableList;
6-
import org.jspecify.annotations.NonNull;
6+
import java.util.Objects;
7+
import org.jspecify.annotations.Nullable;
78
import org.prlprg.fir.feedback.AbstractionFeedback;
89
import org.prlprg.fir.ir.abstraction.Abstraction;
910
import org.prlprg.fir.ir.callee.StaticFnCallee;
1011
import org.prlprg.fir.ir.expression.Call;
1112
import org.prlprg.fir.ir.instruction.Statement;
1213
import org.prlprg.fir.ir.module.Function;
13-
import org.prlprg.fir.ir.type.Type;
1414
import org.prlprg.fir.opt.specialize.OptimizeCallee;
15+
import org.prlprg.util.Lists;
1516

1617
/// If there's a call whose best guaranteed version
1718
/// ([Function#guess(org.prlprg.fir.ir.type.Signature)]) does not exactly match its arguments'
1819
/// static types, copy that version into a new one and narrow the parameter types to match
1920
public record CreateBestVersion(int versionLimit) implements AbstractionOptimization {
2021
public boolean runWithoutRecording(
21-
Function function, AbstractionFeedback feedback, Abstraction version) {
22+
@Nullable Function function, AbstractionFeedback feedback, Abstraction version) {
2223
var calls =
2324
version
2425
.streamCfgs()
@@ -44,16 +45,15 @@ private boolean run(AbstractionFeedback feedback, Abstraction scope, Call call)
4445
}
4546

4647
var callArguments = call.callArguments();
47-
var argumentTypes =
48-
callArguments.stream().map(scope::typeOf).collect(ImmutableList.toImmutableList());
49-
if (argumentTypes.contains(null)) {
48+
if (callArguments.stream().anyMatch(a -> scope.typeOf(a) == null)) {
5049
// Invalid, null type
5150
return false;
5251
}
53-
@SuppressWarnings("RedundantCast")
54-
var argumentTypes1 = (ImmutableList<@NonNull Type>) argumentTypes;
52+
var argumentTypes =
53+
ImmutableList.copyOf(
54+
Lists.mapStrict(callArguments, a -> Objects.requireNonNull(scope.typeOf(a))));
5555

56-
var bestSignature = OptimizeCallee.bestSignature(callee, argumentTypes1);
56+
var bestSignature = OptimizeCallee.bestSignature(callee, argumentTypes);
5757
var bestVersion = calleeFun.guess(bestSignature);
5858
if (bestVersion == null) {
5959
// Invalid, there should always be a possible version
@@ -65,7 +65,7 @@ private boolean run(AbstractionFeedback feedback, Abstraction scope, Call call)
6565
}
6666

6767
// Create a new version with the exact parameter types
68-
copy(feedback.module(), calleeFun, bestVersion, argumentTypes1);
68+
copy(feedback.module(), calleeFun, bestVersion, argumentTypes);
6969
return true;
7070
}
7171
}

0 commit comments

Comments
 (0)