Commit 29689be8 authored by Alexander Weigl's avatar Alexander Weigl

multiple enhancements

* Open in Key
* repair matching of updates
* assignment hooks
parent c8730ab9
Pipeline #15577 failed with stages
in 105 minutes and 4 seconds
...@@ -50,8 +50,17 @@ f(x), f(x,y,g(y)), X, ?Y, _, ..., f(... ?X ...), f(..., ?X), f(..., ...?X...), f ...@@ -50,8 +50,17 @@ f(x), f(x,y,g(y)), X, ?Y, _, ..., f(... ?X ...), f(..., ?X), f(..., ...?X...), f
bindClause : ('\\as' | ':') SID; bindClause : ('\\as' | ':') SID;
ARROW : '⇒' | '==>';
DONTCARE: '?' | '_' | '█'; DONTCARE: '?' | '_' | '█';
DIGITS : DIGIT+ ;
fragment DIGIT : [0-9] ;
SID: '?' [_a-zA-Z0-9\\]+ ;
ID : [a-zA-Z\\_] ([_a-zA-Z0-9\\])*
| 'update-application'
| 'parallel-upd'
| 'elem-update'
;
ARROW : '⇒' | '==>';
STARDONTCARE: '...' | '…'; STARDONTCARE: '...' | '…';
PLUS : '+' ; PLUS : '+' ;
MINUS : '-' ; MINUS : '-' ;
...@@ -72,10 +81,5 @@ XOR:'^'; ...@@ -72,10 +81,5 @@ XOR:'^';
FORALL: '\forall' | '∀'; FORALL: '\forall' | '∀';
EXISTS: '\exists'; EXISTS: '\exists';
DIGITS : DIGIT+ ;
fragment DIGIT : [0-9] ;
SID: '?' [_a-zA-Z0-9\\]+ ;
ID : [a-zA-Z\\_] ([_a-zA-Z0-9\\])*| 'update-application';
COMMENT: '//' ~[\n\r]* -> channel(HIDDEN); COMMENT: '//' ~[\n\r]* -> channel(HIDDEN);
WS: [\n\f\r\t ] -> channel(HIDDEN); WS: [\n\f\r\t ] -> channel(HIDDEN);
...@@ -72,7 +72,7 @@ public class MatcherFacade { ...@@ -72,7 +72,7 @@ public class MatcherFacade {
public static Matchings matches(String pattern, Sequent sequent, boolean catchAll) { public static Matchings matches(String pattern, Sequent sequent, boolean catchAll) {
MatchPatternParser mpp = getParser(pattern); MatchPatternParser mpp = getParser(pattern);
MatchPatternParser.SequentPatternContext ctx = mpp.sequentPattern(); MatchPatternParser.SequentPatternContext ctx = mpp.sequentPattern();
logger.error("Matching \n" + pattern + "\n" + sequent.toString()); logger.info("Matching \n" + pattern + "\n" + sequent.toString());
if (mpp.getNumberOfSyntaxErrors() != 0) { if (mpp.getNumberOfSyntaxErrors() != 0) {
logger.info("Invalid pattern syntax '{}' no matches returned.", pattern); logger.info("Invalid pattern syntax '{}' no matches returned.", pattern);
return new Matchings(); return new Matchings();
......
...@@ -7,7 +7,6 @@ import de.uka.ilkd.key.logic.Term; ...@@ -7,7 +7,6 @@ import de.uka.ilkd.key.logic.Term;
import edu.kit.formal.psdb.termmatcher.MatchPatternLexer; import edu.kit.formal.psdb.termmatcher.MatchPatternLexer;
import edu.kit.formal.psdb.termmatcher.MatchPatternParser; import edu.kit.formal.psdb.termmatcher.MatchPatternParser;
import edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPath; import edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPath;
import static edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPathFacade.*;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.antlr.v4.runtime.CommonToken; import org.antlr.v4.runtime.CommonToken;
...@@ -18,6 +17,8 @@ import java.util.stream.Collectors; ...@@ -18,6 +17,8 @@ import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import static edu.kit.iti.formal.psdbg.termmatcher.mp.MatchPathFacade.*;
/** /**
* Matchpattern visitor visits the matchpatterns of case-statements * Matchpattern visitor visits the matchpatterns of case-statements
* *
...@@ -26,9 +27,13 @@ import java.util.stream.Stream; ...@@ -26,9 +27,13 @@ import java.util.stream.Stream;
*/ */
class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> { class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> {
static final Matchings NO_MATCH = new Matchings(); static final Matchings NO_MATCH = new Matchings();
static final Matchings EMPTY_MATCH = Matchings.singleton("EMPTY_MATCH", null); static final Matchings EMPTY_MATCH = Matchings.singleton("EMPTY_MATCH", null);
static final Map<String, MatchPath> EMPTY_VARIABLE_ASSIGNMENT = EMPTY_MATCH.first(); static final Map<String, MatchPath> EMPTY_VARIABLE_ASSIGNMENT = EMPTY_MATCH.first();
Random random = new Random(42L); Random random = new Random(42L);
/* /*
* Reduce two matchinfos * Reduce two matchinfos
* *
...@@ -61,6 +66,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> { ...@@ -61,6 +66,7 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> {
} }
*/ */
private List<Integer> currentPosition = new ArrayList<>(); private List<Integer> currentPosition = new ArrayList<>();
/** /**
* If true, we assume every term in the pattern has a binder. * If true, we assume every term in the pattern has a binder.
* The binding names are generated. * The binding names are generated.
...@@ -205,9 +211,11 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> { ...@@ -205,9 +211,11 @@ class MatcherImpl extends MatchPatternDualVisitor<Matchings, MatchPath> {
//System.out.format("Match: %25s with %s %n", peek, ctx.toInfoString(new MatchPatternParser(null))); //System.out.format("Match: %25s with %s %n", peek, ctx.toInfoString(new MatchPatternParser(null)));
String expectedFunction = ctx.func.getText(); String expectedFunction = ctx.func.getText();
Term peek = ((MatchPath.MPTerm) path).getUnit(); Term peek = ((MatchPath.MPTerm) path).getUnit();
if (peek.op().name().toString().equals(expectedFunction) // same name boolean sameName = expectedFunction.equals("?")
&& ctx.termPattern().size() == peek.arity() // same arity || expectedFunction.equals("_")
) { || peek.op().name().toString().equals(expectedFunction);
boolean sameArity = ctx.termPattern().size() == peek.arity();
if (sameName && sameArity) {
Matchings m = IntStream.range(0, peek.arity()) Matchings m = IntStream.range(0, peek.arity())
.mapToObj(i -> (Matchings) .mapToObj(i -> (Matchings)
accept(ctx.termPattern(i), create(path, i))) accept(ctx.termPattern(i), create(path, i)))
......
package edu.kit.iti.formal.psdbg.termmatcher;
import de.uka.ilkd.key.api.KeYApi;
import de.uka.ilkd.key.api.ProofApi;
import de.uka.ilkd.key.api.ProofManagementApi;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.proof.init.ProofInputException;
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import java.util.regex.Pattern;
public class TestUpdateMatch {
@Test
public void test() throws ProblemLoaderException, ProofInputException {
ProofManagementApi a = KeYApi.loadFromKeyFile(new File("src/test/resources/edu/kit/iti/formal/psdbg/termmatcher/javasimple/project.key"));
ProofApi pa = a.startProof(a.getProofContracts().get(0));
Sequent sequent = pa.getProof().root().sequent();
System.out.println(sequent);
Matchings result = MatcherFacade.matches("... update-application(_, ?X) ...", sequent, false);
System.out.println(result);
String exp = normalize("\\<{exc=null;try { result=self.foo(_x)@Test;} catch (java.lang.Throwable e) { exc=e; } }\\> (and(and(and(gt(result,Z(0(#))),java.lang.Object::<inv>(heap,self)),equals(exc,null)),all{f:Field}(all{o:java.lang.Object}(or(or(elementOf(o,f,allLocs),and(not(equals(o,null)),not(equals(boolean::select(heapAtPre,o,java.lang.Object::<created>),TRUE)))),equals(any::select(heap,o,f),any::select(heapAtPre,o,f)))))))");
String x = normalize(result.iterator().next().get("?X").getUnit().toString().replace("\n", " "));
Assert.assertEquals(exp, x);
}
private String normalize(String s) {
Pattern re = Pattern.compile("\\s+");
return re.matcher(s).replaceAll(" ");
}
}
public class Test{
/*@ public normal_behavior
@ requires x >= 0;
@ ensures \result >0;
@*/
public int foo(int x){
if(x > 0){
x--;
}else{
x++;
}
return x++;
}
}
\ No newline at end of file
\javaSource "";
\chooseContract
\ No newline at end of file
...@@ -32,8 +32,6 @@ import java.util.stream.Stream; ...@@ -32,8 +32,6 @@ import java.util.stream.Stream;
*/ */
public class Interpreter<T> extends DefaultASTVisitor<Object> public class Interpreter<T> extends DefaultASTVisitor<Object>
implements ScopeObservable { implements ScopeObservable {
private static final int MAX_ITERATIONS = 10000;
protected static Logger logger = LogManager.getLogger(Interpreter.class); protected static Logger logger = LogManager.getLogger(Interpreter.class);
@Getter @Getter
...@@ -43,6 +41,13 @@ public class Interpreter<T> extends DefaultASTVisitor<Object> ...@@ -43,6 +41,13 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
protected List<Visitor> entryListeners = new ArrayList<>(), protected List<Visitor> entryListeners = new ArrayList<>(),
exitListeners = new ArrayList<>(); exitListeners = new ArrayList<>();
/**
*
*/
@Getter
@Setter
private int maxIterationsRepeat = 10000;
private Stack<State<T>> stateStack = new Stack<>(); private Stack<State<T>> stateStack = new Stack<>();
@Getter @Getter
...@@ -54,12 +59,13 @@ public class Interpreter<T> extends DefaultASTVisitor<Object> ...@@ -54,12 +59,13 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
@Getter @Getter
@Setter @Setter
private boolean scrictSelectedGoalMode = false; private boolean strictMode = false;
@Getter @Getter
@Setter @Setter
private VariableAssignmentHook<T> variableAssignmentHook = null; private VariableAssignmentHook<T> variableAssignmentHook = null;
@Getter @Getter
@Setter @Setter
private boolean suppressListeners = false; private boolean suppressListeners = false;
...@@ -551,8 +557,7 @@ public class Interpreter<T> extends DefaultASTVisitor<Object> ...@@ -551,8 +557,7 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
//State<T> newErrorState = newState(null, null); //State<T> newErrorState = newState(null, null);
//newErrorState.setErrorState(true); //newErrorState.setErrorState(true);
//pushState(newErrorState); //pushState(newErrorState);
} } finally {
finally {
g.exitScope(); g.exitScope();
// System.out.println(stateStack.peek().hashCode()); // System.out.println(stateStack.peek().hashCode());
exitScope(call); exitScope(call);
...@@ -627,9 +632,9 @@ public class Interpreter<T> extends DefaultASTVisitor<Object> ...@@ -627,9 +632,9 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
Set<GoalNode<T>> prevNodes = new HashSet<>(prev.getGoals()); Set<GoalNode<T>> prevNodes = new HashSet<>(prev.getGoals());
Set<GoalNode<T>> endNodes = new HashSet<>(end.getGoals()); Set<GoalNode<T>> endNodes = new HashSet<>(end.getGoals());
b = prevNodes.equals(endNodes); b = prevNodes.equals(endNodes);
b = b && counter <= MAX_ITERATIONS; b = b && counter <= maxIterationsRepeat;
} while (b); } while (b);
}catch (InterpreterRuntimeException e) { } catch (InterpreterRuntimeException e) {
logger.debug("Catched!", e); logger.debug("Catched!", e);
} }
exitScope(repeatStatement); exitScope(repeatStatement);
...@@ -655,7 +660,7 @@ public class Interpreter<T> extends DefaultASTVisitor<Object> ...@@ -655,7 +660,7 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
} }
return selectedGoalNode; return selectedGoalNode;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
if (scrictSelectedGoalMode) if (strictMode)
throw e; throw e;
logger.warn("No goal selected. Returning first goal!"); logger.warn("No goal selected. Returning first goal!");
......
package edu.kit.iti.formal.psdbg.interpreter.assignhook;
import edu.kit.iti.formal.psdbg.interpreter.Interpreter;
import edu.kit.iti.formal.psdbg.parser.data.Value;
import lombok.Getter;
import lombok.Setter;
public class InterpreterOptionsHook<T> extends DefaultAssignmentHook<T> {
@Getter
@Setter
private Interpreter<T> interpreter;
public InterpreterOptionsHook(Interpreter<T> interpreter) {
this.interpreter = interpreter;
register("__MAX_ITERATIONS_REPEAT",
(T data, Value v) -> {
interpreter.setMaxIterationsRepeat((Integer) v.getData());
return true;
},
(T data) -> Value.from(interpreter.getMaxIterationsRepeat())
);
register("__STRICT_MODE",
(T data, Value v) -> {
interpreter.setStrictMode((boolean) v.getData());
return true;
},
(T data) -> Value.from(interpreter.isStrictMode())
);
}
}
package de.uka.ilkd.key.macros;
import de.uka.ilkd.key.control.UserInterfaceControl;
import de.uka.ilkd.key.logic.PosInOccurrence;
import de.uka.ilkd.key.macros.ProofMacro;
import de.uka.ilkd.key.proof.Goal;
import de.uka.ilkd.key.proof.Node;
import de.uka.ilkd.key.proof.Proof;
import de.uka.ilkd.key.proof.ProverTaskListener;
import org.key_project.util.collection.ImmutableList;
public class TestGenMacro implements ProofMacro {
@Override
public String getName() {
return "dummy test gen macro";
}
@Override
public String getScriptCommandName() {
return null;
}
@Override
public String getCategory() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public boolean canApplyTo(Proof proof, ImmutableList<Goal> immutableList, PosInOccurrence posInOccurrence) {
return false;
}
@Override
public boolean canApplyTo(Node node, PosInOccurrence posInOccurrence) {
return false;
}
@Override
public ProofMacroFinishedInfo applyTo(UserInterfaceControl userInterfaceControl, Proof proof, ImmutableList<Goal> immutableList, PosInOccurrence posInOccurrence, ProverTaskListener proverTaskListener) throws InterruptedException, Exception {
return null;
}
@Override
public ProofMacroFinishedInfo applyTo(UserInterfaceControl userInterfaceControl, Node node, PosInOccurrence posInOccurrence, ProverTaskListener proverTaskListener) throws InterruptedException, Exception {
return null;
}
}
...@@ -6,9 +6,11 @@ import com.google.common.eventbus.Subscribe; ...@@ -6,9 +6,11 @@ import com.google.common.eventbus.Subscribe;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView;
import de.uka.ilkd.key.api.ProofApi; import de.uka.ilkd.key.api.ProofApi;
import de.uka.ilkd.key.gui.MainWindow;
import de.uka.ilkd.key.proof.Goal; import de.uka.ilkd.key.proof.Goal;
import de.uka.ilkd.key.proof.Node; import de.uka.ilkd.key.proof.Node;
import de.uka.ilkd.key.proof.Proof; import de.uka.ilkd.key.proof.Proof;
import de.uka.ilkd.key.proof.SingleProof;
import de.uka.ilkd.key.proof.init.ProofInputException; import de.uka.ilkd.key.proof.init.ProofInputException;
import de.uka.ilkd.key.proof.io.ProblemLoaderException; import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.speclang.Contract;
...@@ -26,7 +28,6 @@ import edu.kit.iti.formal.psdbg.interpreter.KeYProofFacade; ...@@ -26,7 +28,6 @@ import edu.kit.iti.formal.psdbg.interpreter.KeYProofFacade;
import edu.kit.iti.formal.psdbg.interpreter.KeyInterpreter; import edu.kit.iti.formal.psdbg.interpreter.KeyInterpreter;
import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode; import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData; import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.State;
import edu.kit.iti.formal.psdbg.interpreter.dbg.*; import edu.kit.iti.formal.psdbg.interpreter.dbg.*;
import edu.kit.iti.formal.psdbg.parser.ast.ProofScript; import edu.kit.iti.formal.psdbg.parser.ast.ProofScript;
import javafx.application.Platform; import javafx.application.Platform;
...@@ -55,6 +56,7 @@ import org.reactfx.util.FxTimer; ...@@ -55,6 +56,7 @@ import org.reactfx.util.FxTimer;
import org.reactfx.util.Timer; import org.reactfx.util.Timer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.swing.*;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
...@@ -82,13 +84,13 @@ public class DebuggerMain implements Initializable { ...@@ -82,13 +84,13 @@ public class DebuggerMain implements Initializable {
public final ContractLoaderService contractLoaderService = new ContractLoaderService(); public final ContractLoaderService contractLoaderService = new ContractLoaderService();
private InspectionViewsController inspectionViewsController;
private final ExecutorService executorService = Executors.newFixedThreadPool(2); private final ExecutorService executorService = Executors.newFixedThreadPool(2);
@Getter @Getter
private final DebuggerMainModel model = new DebuggerMainModel(); private final DebuggerMainModel model = new DebuggerMainModel();
private InspectionViewsController inspectionViewsController;
private ScriptController scriptController; private ScriptController scriptController;
@FXML @FXML
...@@ -868,7 +870,7 @@ public class DebuggerMain implements Initializable { ...@@ -868,7 +870,7 @@ public class DebuggerMain implements Initializable {
interactiveModeController.start(getFacade().getProof(), getInspectionViewsController().getActiveInspectionViewTab().getModel()); interactiveModeController.start(getFacade().getProof(), getInspectionViewsController().getActiveInspectionViewTab().getModel());
} else { } else {
interactiveModeController.stop(); interactiveModeController.stop();
} }
} }
@FXML @FXML
...@@ -953,6 +955,24 @@ public class DebuggerMain implements Initializable { ...@@ -953,6 +955,24 @@ public class DebuggerMain implements Initializable {
}); });
} }
public void openInKey(@Nullable ActionEvent event) {
if (FACADE.getProofState() == KeYProofFacade.ProofState.EMPTY) {
Alert alert = new Alert(Alert.AlertType.ERROR, "No proof is loaded", ButtonType.OK);
alert.show();
return;
}
SwingUtilities.invokeLater(() -> {
// Swing Thread!
MainWindow keyWindow = MainWindow.getInstance();
keyWindow.addProblem(new SingleProof(FACADE.getProof(), "script"));
//keyWindow.getProofList().getModel().addProof();
keyWindow.makePrettyView();
keyWindow.setVisible(true);
});
}
public class ContractLoaderService extends Service<List<Contract>> { public class ContractLoaderService extends Service<List<Contract>> {
@Override @Override
protected void succeeded() { protected void succeeded() {
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
</Menu> </Menu>
<Menu text="Edit"> <Menu text="Edit">
<items> <items>
<MenuItem text="Open in KeY" onAction="#openInKey"/>
<MenuItem text="Delete"/> <MenuItem text="Delete"/>
<MenuItem text="Reformat" accelerator="Ctrl+Shift+f" onAction="#reformatCurrentEditor"/> <MenuItem text="Reformat" accelerator="Ctrl+Shift+f" onAction="#reformatCurrentEditor"/>
<MenuItem text="Print Debug Information" onAction="#debugPrintDot" <MenuItem text="Print Debug Information" onAction="#debugPrintDot"
......
MathJax.Hub.Config({
config: ["MMLorHTML.js"],
jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
extensions: ["MathMenu.js", "MathZoom.js"]
});
# -*- coding: utf-8 -*-
'''
Math extension for Python-Markdown
==================================
Adds support for displaying math formulas using
[MathJax](http://www.mathjax.org/).
Author: 2015-2017, Dmitry Shachnev <mitya57@gmail.com>.
'''
from markdown.inlinepatterns import Pattern
from markdown.extensions import Extension
from markdown.util import AtomicString, etree
class MathExtension(Extension):
def __init__(self, *args, **kwargs):
self.config = {
'enable_dollar_delimiter':
[False, 'Enable single-dollar delimiter'],
'add_preview': [False, 'Add a preview node before each math node'],
'use_asciimath':
[False, 'Use AsciiMath syntax instead of TeX syntax'],
}
super(MathExtension, self).__init__(*args, **kwargs)
def _get_content_type(self):
if self.getConfig('use_asciimath'):
return 'math/asciimath'
return 'math/tex'
def extendMarkdown(self, md, md_globals):
def _wrap_node(node, preview_text, wrapper_tag):
if not self.getConfig('add_preview'):
return node
preview = etree.Element('span', {'class': 'MathJax_Preview'})
preview.text = AtomicString(preview_text)
wrapper = etree.Element(wrapper_tag)
wrapper.extend([preview, node])
return wrapper
def handle_match_inline(m):
node = etree.Element('script')
node.set('type', self._get_content_type())
node.text = AtomicString(m.group(3))
return _wrap_node(node, ''.join(m.group(2, 3, 4)), 'span')
def handle_match(m):
node = etree.Element('script')
node.set('type', '%s; mode=display' % self._get_content_type())
if '\\begin' in m.group(2):
node.text = AtomicString(''.join(m.group(2, 4, 5)))
return _wrap_node(node, ''.join(m.group(1, 2, 4, 5, 6)), 'div')
else:
node.text = AtomicString(m.group(3))
return _wrap_node(node, ''.join(m.group(2, 3, 4)), 'div')
inlinemathpatterns = (
Pattern(r'(?<!\\|\$)(\$)([^\$]+)(\$)'), # $...$
Pattern(r'(?<!\\)(\\\()(.+?)(\\\))') # \(...\)
)
mathpatterns = (
Pattern(r'(?<!\\)(\$\$)([^\$]+)(\$\$)'), # $$...$$
Pattern(r'(?<!\\)(\\\[)(.+?)(\\\])'), # \[...\]
Pattern(r'(?<!\\)(\\begin{([a-z]+?\*?)})(.+?)(\\end{\3})')
)
if not self.getConfig('enable_dollar_delimiter'):
inlinemathpatterns = inlinemathpatterns[1:]
for i, pattern in enumerate(mathpatterns):
pattern.handleMatch = handle_match
md.inlinePatterns.add('math-%d' % i, pattern, '<escape')
for i, pattern in enumerate(inlinemathpatterns):
pattern.handleMatch = handle_match_inline
md.inlinePatterns.add('math-inline-%d' % i, pattern, '<escape')
if self.getConfig('enable_dollar_delimiter'):
md.ESCAPED_CHARS.append('$')
def makeExtension(*args, **kwargs):
return MathExtension(*args, **kwargs)
\ No newline at end of file
# Variables
The proof script language supports script variables.
These are variables that are managed by the interpreter and are not part of the explicit proof
object&mdash;in contrast to the variables of the
Java program and the logical variables of first oder logic formulas.
As Java or logic variables, we bind the assignments script variables to a sequences.
If a script variable is not assigned in the current selected goal,
we look up its value in the sequence's ancestors, recursively.
## Types