Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove KLabel variables #3877

Merged
merged 5 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion k-distribution/include/kframework/builtin/kast.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ module KSEQ-SYMBOLIC
syntax KConfigVar ::= r"(?<![A-Za-z0-9_\\$!\\?@])(\\$)([A-Z][A-Za-z0-9'_]*)" [token]
syntax KBott ::= #KVariable
syntax KBott ::= KConfigVar
syntax KLabel ::= #KVariable
endmodule
```

Expand Down
2 changes: 1 addition & 1 deletion k-distribution/tests/regression-new/issue-1528/3.test.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<k>
bar ( 1 , 0 ) ~> bar ( 1 , 0 ) ~> bar ( 1 , 0 ) ~> .
bar ( 0 , 1 ) ~> bar ( 0 , 1 ) ~> bar ( 0 , 1 ) ~> .
</k>
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,6 @@ public static Sort lubSort(
}

private Production production(KApply term) {
if (term.klabel() instanceof KVariable) {
throw KEMException.internalError("KORE does not yet support KLabel variables.", term);
}
Option<scala.collection.Set<Production>> prods = mod.productionsFor().get(term.klabel().head());
if (prods.isEmpty()) {
throw KEMException.compilerError(
Expand Down
84 changes: 55 additions & 29 deletions kernel/src/main/java/org/kframework/parser/binary/BinaryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.kframework.kore.K;
import org.kframework.kore.KLabel;
import org.kframework.kore.KToken;
Expand All @@ -24,25 +25,30 @@
* <p>Format of the KAST binary term is as follows:
*
* <p>First five bytes are the magic header "\x7fKAST". Next 3 bytes are the major, minor, and
* release version of the format. Currently they are set to "\x04\x00\x00".
* release version of the format. Currently, they are set to "\x04\x01\x00".
*
* <p>Subsequently, the format contains a post-order traversal of the term according to the
* following rules:
*
* <p>* KToken: the byte "\x01" followed by a representation of the string of the token, and then
* the sort of the token. * KApply: Representation of each child of the KApply followed by the byte
* "\x02" followed by a representation of the klabel, followed by a 4-byte arity of the KApply. *
* KSequence: Representation of each child of the KSequence followed by the byte "\x03" followed by
* a 4-byte length of the KSequence. * KVariable: The byte "\x04" followed by a representation of
* the name of the variable. * KRewrite: Representation of the LHS of the rewrite, followed by the
* RHS, followed by the byte "\x05". * InjectedKLabel: The byte "\x06" followed by the
* representation of the klabel. * KLabel: The representation of the string of the klabel, followed
* by the byte "\x01" if the klabel is a variable, and "\x00" if it's a concrete klabel. * String: A
* 4-byte offset in the string intern table. The intern table is commputed as the term is traversed.
* An offset of 0 means that the string has not appeared before in this term, and is followed by a
* 4-byte length of the string followed by the String in UTF-16. An offset of 1 means the string
* refers to the most recent previous string in the intern table. An offset of 2 means the
* next-most-recent, and so forth.
* <ul>
* <li>KToken: the byte "\x01" followed by a representation of the string of the token, and then
* the sort of the token.
* <li>KApply: Representation of each child of the KApply followed by the byte "\x02" followed by
* a representation of the klabel, followed by a 4-byte arity of the KApply.
* <li>KSequence: Representation of each child of the KSequence followed by the byte "\x03"
* followed by a 4-byte length of the KSequence.
* <li>KVariable: The byte "\x04" followed by a representation of the name of the variable.
* <li>KRewrite: Representation of the LHS of the rewrite, followed by the RHS, followed by the
* byte "\x05".
* <li>InjectedKLabel: The byte "\x06" followed by the representation of the klabel.
* <li>KLabel: The representation of the string of the klabel, followed by the byte "\x01" if the
* klabel is a variable, and "\x00" if it's a concrete klabel.
* <li>String: A 4-byte offset in the string intern table. The intern table is computed as the
* term is traversed. An offset of 0 means that the string has not appeared before in this
* term, and is followed by a 4-byte length of the string followed by the String in UTF-16. An
* offset of 1 means the string refers to the most recent previous string in the intern table.
* An offset of 2 means the next-most-recent, and so forth.
* </ul>
*
* <p>Note one exception to this rule in binary format 4.0.1: if a term is encountered that has
* already been serialized, instead of serializing it again we serialize the byte '\x08' followed by
Expand Down Expand Up @@ -80,8 +86,24 @@ private BinaryParser(ByteBuffer data) {
this.data = data;
}

private K read400(boolean _401) throws IOException {
// Version information ordered lexicographically by (major, minor, build)
private record BinaryVersion(Integer major, Integer minor, Integer build)
implements Comparable<BinaryVersion> {
@Override
public int compareTo(@NotNull BinaryVersion other) {
int majorComp = major.compareTo(other.major);
if (majorComp != 0) {
return majorComp;
}
int minorComp = minor.compareTo(other.minor);
if (minorComp != 0) {
return minorComp;
}
return build.compareTo(other.build);
}
}

private K read(BinaryVersion version) throws IOException {
Deque<K> stack = new ArrayDeque<>();
int type = 0;
while (type != END) {
Expand All @@ -98,7 +120,7 @@ private K read400(boolean _401) throws IOException {
stack.push(token);
break;
case KAPPLY:
KLabel lbl = readKLabel();
KLabel lbl = readKLabel(version);
arity = data.getInt();
if (arity == 0) items = EMPTY_KLIST;
else items = new K[arity];
Expand All @@ -125,12 +147,12 @@ private K read400(boolean _401) throws IOException {
stack.push(KRewrite(left, right));
break;
case INJECTEDKLABEL:
stack.push(InjectedKLabel(readKLabel()));
stack.push(InjectedKLabel(readKLabel(version)));
break;
case END:
break;
case BACK_REFERENCE:
if (!_401)
if (version.compareTo(new BinaryVersion(4, 0, 1)) < 0)
throw KEMException.criticalError("Unexpected code found in KAST binary term: " + type);
int idx = data.getInt();
stack.push(kInterns.get(kInterns.size() - idx));
Expand All @@ -151,13 +173,18 @@ private K read400(boolean _401) throws IOException {
private final Map<String, KLabel> klabelCache = new HashMap<>();
private final Map<String, Map<String, KToken>> ktokenCache = new HashMap<>();

private KLabel readKLabel() throws IOException {
private KLabel readKLabel(BinaryVersion version) {
String lbl = readString();
if (data.get() != 0) return KVariable(lbl);
if (version.compareTo(new BinaryVersion(4, 1, 0)) < 0) {
if (data.get() == 1) {
throw KEMException.compilerError(
"Binary data contains variable KLabel, but this is no longer supported.");
}
}
return klabelCache.computeIfAbsent(lbl, org.kframework.kore.KORE::KLabel);
}

private String readString() throws IOException {
private String readString() {
int idx = data.getInt();
if (idx == 0) {
int len = data.getInt();
Expand Down Expand Up @@ -192,14 +219,13 @@ public static K parse(ByteBuffer data) {
int major = data.get();
int minor = data.get();
int build = data.get();
if (major == 4 && minor == 0 && build == 0) {
return new BinaryParser(data).read400(false);
} else if (major == 4 && minor == 0 && build == 1) {
return new BinaryParser(data).read400(true);
} else {
throw KEMException.compilerError(
"Unsupported version of KAST binary file: " + major + "." + minor + "." + build);
if ((major == 4 && minor == 0 && build == 0)
|| (major == 4 && minor == 0 && build == 1)
|| (major == 4 && minor == 1 && build == 0)) {
return new BinaryParser(data).read(new BinaryVersion(major, minor, build));
}
throw KEMException.compilerError(
"Unsupported version of KAST binary file: " + major + "." + minor + "." + build);
} catch (IOException e) {
throw KEMException.criticalError("Could not read K term from binary", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.kframework.builtin.KLabels;
import org.kframework.builtin.Sorts;
import org.kframework.definition.Module;
import org.kframework.definition.Production;
import org.kframework.parser.Ambiguity;
Expand Down Expand Up @@ -48,15 +47,10 @@ public Either<java.util.Set<KEMException>, Term> apply(TermCons tc) {
assert tc.production() != null : this.getClass() + ":" + " production not found." + tc;
if (tc.production().klabel().isDefined()
&& tc.production().klabel().get().equals(KLabels.KAPP)) {
if (!(tc.get(0) instanceof Constant kl)
|| !((Constant) tc.get(0)).production().sort().equals(Sorts.KLabel()))
// TODO: remove check once the java backend is no longer supported.
return super.apply(
tc); // don't do anything if the label is not a token KLabel (in case of variable or
// casted variable)
Constant kl = (Constant) tc.get(0);
String klvalue = kl.value();
try {
klvalue = StringUtil.unescapeKoreKLabel(kl.value());
klvalue = StringUtil.unescapeKoreKLabel(klvalue);
} catch (IllegalArgumentException e) {
/* ignore */
} // if possible, unescape
Expand All @@ -81,7 +75,7 @@ public Either<java.util.Set<KEMException>, Term> apply(TermCons tc) {
sol.add(TermCons.apply(terms, prd, tc.location(), tc.source()));

if (sol.size() == 0) {
String msg = "Could not find any suitable production for label " + kl.value();
String msg = "Could not find any suitable productions for label " + kl.value();
return Left.apply(Sets.newHashSet(KEMException.innerParserError(msg, kl)));
} else if (sol.size() == 1) {
return super.apply(sol.iterator().next());
Expand Down
4 changes: 1 addition & 3 deletions kernel/src/main/java/org/kframework/unparser/ToBinary.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public static void apply(OutputStream out, K k) {
data.writeBytes("KAST");
// version
data.writeByte(4);
data.writeByte(0);
data.writeByte(1);
data.writeByte(0);
new ToBinary(data).traverse(k);
data.writeByte(BinaryParser.END);
} catch (IOException e) {
Expand Down Expand Up @@ -78,7 +78,6 @@ private void traverse(K k) throws IOException {
data.writeByte(BinaryParser.KAPPLY);
add_intern(k);
writeString(app.klabel().name());
data.writeBoolean(app.klabel() instanceof KVariable);
data.writeInt(app.size());

} else if (k instanceof KSequence seq) {
Expand Down Expand Up @@ -108,7 +107,6 @@ private void traverse(K k) throws IOException {
data.writeByte(BinaryParser.INJECTEDKLABEL);
add_intern(k);
writeString(inj.klabel().name());
data.writeBoolean(inj.klabel() instanceof KVariable);

} else {
throw KEMException.criticalError("Unimplemented for Binary serialization: ", k);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class RuleGrammarTest {
private FileUtil files;

@Before
public void setUp() throws Exception {
public void setUp() {
gen = makeRuleGrammarGenerator();
}

Expand Down Expand Up @@ -268,8 +268,10 @@ public void test10() {
+ "syntax Exp ::= Exp \",\" Exp [klabel('Plus), prefer] "
+ "| Exp \"*\" Exp [klabel('Mul)] "
+ "| r\"[0-9]+\" [token] "
+ "| Foo(K, K, K) "
+ "syntax K "
+ "endmodule";
parseRule("A::KLabel(B::K, C::K, D::K)", def, 0, false);
parseRule("Foo(B::K, C::K, D::K)", def, 0, false);
}

// test config cells
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.kframework.kore.K;
import org.kframework.kore.KLabel;
import org.kframework.parser.binary.BinaryParser;
import org.kframework.utils.file.FileUtil;

Expand All @@ -26,17 +27,17 @@ public class BinaryKASTTest {
KRewrite(KVariable("Baz"), KVariable("Baz2")),
InjectedKLabel(KLabel("_+_")),
KApply(KLabel("foo")))),
KApply(KVariable("Lbl"), sharedTerm, sharedTerm, sharedTerm2, sharedTerm));
KApply(KLabel("Lbl"), sharedTerm, sharedTerm, sharedTerm2, sharedTerm));

@Test
public void testWriteThenRead() throws Exception {
public void testWriteThenRead() {
byte[] str = ToBinary.apply(term);
K result2 = BinaryParser.parse(str);
assertEquals(term, result2);
}

@Test
public void testConcatenate() throws Exception {
public void testConcatenate() {
byte[] str = ToBinary.apply(term);
byte[] krewrite = new byte[str.length * 2 - 8];
System.arraycopy(str, 0, krewrite, 0, str.length - 1);
Expand All @@ -49,7 +50,7 @@ public void testConcatenate() throws Exception {

@Test
@Ignore
public void testLarger() throws Exception {
public void testLarger() {
FileUtil.testFileUtil();
byte[] kast = FileUtil.loadBytes(new File("/home/dwightguth/c-semantics/tmp-kcc-FzjROvt"));
K result = BinaryParser.parse(kast);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void testUnparseThenParse() throws Exception {
KApply(
KLabel("<T>"),
terms.get(3),
KApply(KVariable("Lbl"), terms.get(0), terms.get(0), terms.get(1), terms.get(0))));
KApply(KLabel("Lbl"), terms.get(0), terms.get(0), terms.get(1), terms.get(0))));

for (K term : terms) {
for (OutputModes outputMode : outputModes) {
Expand Down
9 changes: 2 additions & 7 deletions kore/src/main/scala/org/kframework/kore/ADT.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// Copyright (c) K Team. All Rights Reserved.
package org.kframework.kore

import collection.JavaConverters._
import org.kframework.attributes._
import org.kframework.builtin.KLabels
import org.kframework.builtin.Sorts
import org.kframework.kore
import org.kframework.kore.KORE.Sort
import scala.collection.JavaConverters._

/**
* Abstract Data Types: basic implementations for the inner KORE interfaces.
Expand Down Expand Up @@ -69,9 +68,7 @@ object ADT {
)
}

case class KVariable(name: String, att: Att = Att.empty) extends kore.KVariable {
def params = Seq()
}
case class KVariable(name: String, att: Att = Att.empty) extends kore.KVariable {}

case class Sort(name: String, params: kore.Sort*) extends kore.Sort {
override def toString =
Expand Down Expand Up @@ -113,8 +110,6 @@ object SortedADT {
val sort: Sort =
if (att.contains(Att.CELL_SORT)) Sorts.K else att.getOptional(classOf[Sort]).orElse(Sorts.K)

def params = Seq()

override def equals(other: Any) = other match {
case v: SortedKVariable => name == v.name && sort == v.sort
// case v: KVariable => throw new UnsupportedOperationException(s"should not mix
Expand Down
9 changes: 7 additions & 2 deletions kore/src/main/scala/org/kframework/kore/interface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,15 @@ trait KApply extends KItem with KCollection {

trait KSequence extends KCollection with K

trait KVariable extends KItem with KLabel {
trait KVariable extends KItem {
def name: String

def computeHashCode = name.hashCode
override def equals(other: Any): Boolean = other match {
case l: KVariable => this.name == l.name
case _ => false
}

override def computeHashCode: Int = name.hashCode
}

trait KAs extends K {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,8 @@ class TreeNodesToKORE(parseSort: java.util.function.Function[String, Sort]) {
items.map(down _)

def downKLabel(t: K): KLabel = t match {
case t @ KToken(s, sort) if sort == Sorts.KVariable =>
KVariable(s.trim, t.att)

case t @ KToken(s, sort) if sort == Sorts.KLabel =>
KLabel(unquote(t))

case t @ KApply(KLabel(s), items) if s.startsWith("#SemanticCastTo") =>
downKLabel(items.head)
}

def locationToAtt(l: Optional[Location], s: Optional[Source]): Att = {
Expand Down