Skip to content

Commit

Permalink
@wip IR: rebase fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakobeha committed Aug 8, 2024
1 parent 22093b8 commit b4c0d08
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 28 deletions.
18 changes: 14 additions & 4 deletions src/main/java/org/prlprg/rds/RDSReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.prlprg.sexp.StrSXP;
import org.prlprg.sexp.TaggedElem;
import org.prlprg.sexp.UserEnvSXP;
import org.prlprg.sexp.ValueSXP;
import org.prlprg.sexp.VecSXP;
import org.prlprg.util.IO;

Expand Down Expand Up @@ -204,12 +205,21 @@ private SEXP readPromise(Flags flags) throws IOException {
if (tag instanceof NilSXP) {
// If the tag is nil, the promise is eager. We put `EMPTY_ENV` instead of nil as the promise
// environment (it can be anything, since it's only used for lazy evaluation).
return new PromSXP<>(expr, val, SEXPs.EMPTY_ENV);
if (val == null) {
throw new RDSException(
"Promise serialized with nil tag but no value (so it's lazy, but evaluating in GNU-R would crash because the environment is `NULL`)");
}
if (!(val instanceof ValueSXP v)) {
throw new RDSException("Nested promise");
}
return new PromSXP<>(expr, v, SEXPs.EMPTY_ENV);
} else if (tag instanceof EnvSXP env) {
// Otherwise, the tag should be an environment, the promise's environment, and the promise is
// lazy. The "value" of a lazy promise is "unbound", which we represent as `null`.
assert val == null
: "promise serialized with env but not unbound value (so the environment is redundant, GNU-R doesn't serialize promises like this)";
if (val != null) {
throw new RDSException(
"Promise serialized with env but not unbound value (so the environment is redundant, GNU-R doesn't serialize promises like this)");
}
return new PromSXP<>(expr, null, env);
} else {
throw new RDSException("Expected promise ENV to be environment");
Expand Down Expand Up @@ -601,7 +611,7 @@ private ListSXP readList(Flags flags) throws IOException {
flags = readFlags();
}

return SEXPs.list(data.build(), attributes);
return SEXPs.list(data.build(), Objects.requireNonNull(attributes));
}

private CloSXP readClosure(Flags flags) throws IOException {
Expand Down
50 changes: 26 additions & 24 deletions src/main/java/org/prlprg/rds/RDSWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public void writeItemOrUnbound(@Nullable SEXP s) throws IOException {
case RDSItemType.Special special -> {
switch (special) {
case RDSItemType.Special.NAMESPACESXP -> {
Objects.requireNonNull(s);
// add to the ref table
refAdd(s);
// write details about the namespace
Expand All @@ -111,10 +112,13 @@ public void writeItemOrUnbound(@Nullable SEXP s) throws IOException {
case RDSItemType.Sexp _ -> {
// Otherwise, write the sexp as normal
switch (s) {
case SymSXP sym -> writeSymbol(sym);
case RegSymSXP sym -> writeRegSymbol(sym);
case MissingSXP _ -> throw new UnsupportedOperationException("can't directly serialize the missing value");
case null -> throw new UnsupportedOperationException("can't serialize the unbound value");
case EnvSXP env -> writeEnv(env);
case ListSXP list -> writeListSXP(list);
case LangSXP lang -> writeLangSXP(lang);
case DotsListSXP _ -> throw new UnsupportedOperationException("can't directly serialize a dots list");
case PromSXP<?> prom -> writePromSXP(prom);
case CloSXP clo -> writeCloSXP(clo);
case BuiltinOrSpecialSXP bos -> writeBuiltinOrSpecialSXP(bos);
Expand Down Expand Up @@ -174,7 +178,7 @@ private RDSItemType rdsType(@Nullable SEXP s) {
case BaseEnvSXP _ -> RDSItemType.Special.BASEENV_SXP;
case GlobalEnvSXP _ -> RDSItemType.Special.GLOBALENV_SXP;
// Non-"Save Special" cases
case NamespaceEnvSXP ns -> RDSItemType.Special.NAMESPACESXP;
case NamespaceEnvSXP _ -> RDSItemType.Special.NAMESPACESXP;
case MissingSXP _ -> RDSItemType.Special.MISSINGARG_SXP;
case null -> RDSItemType.Special.UNBOUNDVALUE_SXP;
default -> new RDSItemType.Sexp(s.type());
Expand Down Expand Up @@ -309,19 +313,14 @@ private void writeEnv(EnvSXP env) throws IOException {
}
}

private void writeSymbol(SymSXP s) throws IOException {
switch (s) {
case RegSymSXP rs -> {
// Add to the ref table
refAdd(rs);
// Write the symbol
writeChars(rs.name());
}
case MissingSXP _ -> throw new UnsupportedOperationException("can't directly serialize the missing value");
}
private void writeRegSymbol(RegSymSXP rs) throws IOException {
// Add to the ref table
refAdd(rs);
// Write the symbol
writeChars(rs.name());
}

private void writeBuiltinOrSpecialSXP(BuiltinOrSpecialSXP bos) throws IOException {
private void writeBuiltinOrSpecialSXP(BuiltinOrSpecialSXP bos) {
// For now, we throw an exception upon writing any SpecialSXP or BuiltinSXP. This is because
// RDS serializes builtins via their name, but we do not have any (fully implemented) construct
// representing the name of a builtin (instead, they are represented with indices)
Expand Down Expand Up @@ -464,16 +463,18 @@ private void scanForCircles(SEXP sexp, HashMap<SEXP, Integer> reps, HashSet<SEXP
scanForCircles(lang.fun(), reps, seen);
lang.args().values().forEach((el) -> scanForCircles(el, reps, seen));
}
case ListSXP list -> {
// For ListSXP, we scan the values
list.values().forEach((el) -> scanForCircles(el, reps, seen));
// For ListSXP, we scan the values
case ListSXP list ->
list.values().forEach((el) -> scanForCircles(el, reps, seen));
case DotsListSXP _ -> {
// Do nothing
}
}
}
case BCodeSXP bc -> {
// For bytecode, we scan the constant pool
// For bytecode, we scan the constant pool
case BCodeSXP bc ->
bc.bc().consts().forEach((el) -> scanForCircles(el, reps, seen));
}

default -> {
// do nothing
}
Expand Down Expand Up @@ -512,8 +513,9 @@ private void writeByteCodeLang(SEXP s, HashMap<SEXP, Integer> reps, AtomicIntege
if (lol.hasAttributes()) {
type =
switch (lol) {
case LangSXP _lang -> RDSItemType.Special.ATTRLANGSXP;
case ListSXP _list -> RDSItemType.Special.ATTRLISTSXP;
case LangSXP _ -> RDSItemType.Special.ATTRLANGSXP;
case ListSXP _ -> RDSItemType.Special.ATTRLISTSXP;
case DotsListSXP _ -> throw new UnreachableError();
};
}
out.writeInt(type.i());
Expand Down Expand Up @@ -543,6 +545,7 @@ private void writeByteCodeLang(SEXP s, HashMap<SEXP, Integer> reps, AtomicIntege
// write tail
writeByteCodeLang(list.subList(1), reps, nextRepIndex);
}
case DotsListSXP _ -> throw new UnreachableError();
}
} else { // Print a zero as padding and write the item normally
out.writeInt(0);
Expand Down Expand Up @@ -577,10 +580,9 @@ private void writeByteCodeConsts(
out.writeInt(c.type().i);
writeByteCode1(bc, reps, nextRepIndex);
}
case AbstractPairListSXP l -> {
// writeBCLang writes the type i
// writeBCLang writes the type i
case AbstractPairListSXP l ->
writeByteCodeLang(l, reps, nextRepIndex);
}
default -> {
out.writeInt(c.type().i);
writeItem(c);
Expand Down

0 comments on commit b4c0d08

Please sign in to comment.