hu.bme.mit.theta.sts.parser.StsInterpreter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of theta-sts Show documentation
Show all versions of theta-sts Show documentation
Sts subproject in the Theta model checking framework
/*
* Copyright 2024 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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 hu.bme.mit.theta.sts.parser;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static hu.bme.mit.theta.common.Utils.head;
import static hu.bme.mit.theta.common.Utils.tail;
import static hu.bme.mit.theta.core.decl.Decls.Var;
import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool;
import static hu.bme.mit.theta.core.utils.TypeUtils.cast;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import com.google.common.primitives.Ints;
import hu.bme.mit.theta.common.parser.SExpr;
import hu.bme.mit.theta.common.parser.SExpr.SAtom;
import hu.bme.mit.theta.common.parser.SExpr.SList;
import hu.bme.mit.theta.core.decl.VarDecl;
import hu.bme.mit.theta.core.parser.CoreInterpreter;
import hu.bme.mit.theta.core.parser.Env;
import hu.bme.mit.theta.core.type.Expr;
import hu.bme.mit.theta.core.type.Type;
import hu.bme.mit.theta.core.type.anytype.PrimeExpr;
import hu.bme.mit.theta.core.type.booltype.BoolType;
import hu.bme.mit.theta.sts.STS;
import hu.bme.mit.theta.sts.STS.Builder;
final class StsInterpreter {
private final Env env;
private final CoreInterpreter interpreter;
public StsInterpreter(final Env env) {
this.env = checkNotNull(env);
interpreter = new CoreInterpreter(env);
initEnv();
}
private void initEnv() {
interpreter.defineCommonTypes();
interpreter.defineCommonExprs();
interpreter.defineExpr("prime", interpreter.exprUnaryOperator(PrimeExpr::of));
env.define("system", stsCreator());
env.define("var", varCreator());
env.define("init", stsExprCreator(Context.INIT));
env.define("invar", stsExprCreator(Context.INVAR));
env.define("trans", stsExprCreator(Context.TRANS));
env.define("prop", stsExprCreator(Context.PROP));
}
public STS sts(final SExpr sexpr) {
return (STS) eval(sexpr);
}
private Object eval(final SExpr sexpr) {
if (sexpr.isAtom()) {
return evalAtom(sexpr.asAtom());
} else if (sexpr.isList()) {
return evalList(sexpr.asList());
} else {
throw new AssertionError();
}
}
private Object evalAtom(final SAtom satom) {
final String symbol = satom.getAtom();
final Integer integer = Ints.tryParse(symbol);
if (integer != null) {
return integer;
} else {
final Object value = env.eval(symbol);
return value;
}
}
private Object evalList(final SList slist) {
final List list = slist.getList();
final SExpr head = head(list);
final List tail = tail(list);
if (head.isAtom()) {
final String symbol = head.asAtom().getAtom();
final Object object = env.eval(symbol);
@SuppressWarnings("unchecked") final Function, ?> interpretation = (Function, ?>) object;
final Object value = interpretation.apply(tail);
return value;
} else if (head.isList()) {
throw new UnsupportedOperationException();
} else {
throw new AssertionError();
}
}
private Function, STS> stsCreator() {
return sexprs -> {
final Builder builder = STS.builder();
env.push();
for (final SExpr sexpr : sexprs) {
final Object object = eval(sexpr);
if (object instanceof VarDecl) {
final VarDecl> varDecl = (VarDecl>) object;
env.define(varDecl.getName(), varDecl);
} else if (object instanceof ExprContext) {
final ExprContext exprContext = (ExprContext) object;
exprContext.apply(builder);
} else {
throw new UnsupportedOperationException();
}
}
env.pop();
return builder.build();
};
}
private Function, VarDecl>> varCreator() {
return sexprs -> {
checkArgument(sexprs.size() == 2);
final String name = sexprs.get(0).asAtom().getAtom();
final Type type = interpreter.type(sexprs.get(1));
final VarDecl> varDecl = Var(name, type);
return varDecl;
};
}
private Function, ExprContext> stsExprCreator(final Context context) {
return sexprs -> {
checkArgument(sexprs.size() == 1);
final Expr> expr = interpreter.expr(sexprs.get(0));
return ExprContext.of(context, expr);
};
}
private static final class ExprContext {
private final Context context;
private final Expr expr;
private ExprContext(final Context context, final Expr> expr) {
this.context = checkNotNull(context);
this.expr = cast(checkNotNull(expr), Bool());
}
public static ExprContext of(final Context context, final Expr> expr) {
return new ExprContext(context, expr);
}
public void apply(final STS.Builder builder) {
context.apply(builder, expr);
}
}
private enum Context {
INIT((b, e) -> b.addInit(e)),
INVAR((b, e) -> b.addInvar(e)),
TRANS((b, e) -> b.addTrans(e)),
PROP((b, e) -> b.setProp(e));
private final BiConsumer> consumer;
private Context(final BiConsumer> consumer) {
this.consumer = checkNotNull(consumer);
}
public void apply(final STS.Builder builder, final Expr expr) {
consumer.accept(builder, expr);
}
}
}