Skip to content

Commit

Permalink
#99 Improve Context and $ContextPath handling in packages
Browse files Browse the repository at this point in the history
  • Loading branch information
axkr committed Nov 1, 2018
1 parent 01d1a84 commit d5a1bf9
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static class $Context extends AbstractSymbolEvaluator {

@Override
public IExpr evaluate(final ISymbol symbol) {
return EvalEngine.get().getContextPath().currentContext();
return EvalEngine.get().getContextPath().currentContextString();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ public static class End extends AbstractCoreFunctionEvaluator {
@Override
public IExpr evaluate(final IAST ast, EvalEngine engine) {
Context context = engine.end();
if (context==null) {
return F.NIL;
}
return F.stringx(context.getContextName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,6 @@ public static void set(final EvalEngine engine) {

transient Stack<ContextPath> fContextPathStack;

transient Context fContext;

transient ContextPath fContextPath;

protected int fRecursionLimit;
Expand Down Expand Up @@ -374,7 +372,6 @@ public EvalEngine copy() {
engine.REMEMBER_AST_CACHE = REMEMBER_AST_CACHE;
engine.fAnswer = fAnswer;
engine.fAssumptions = fAssumptions;
engine.fContext = fContext;
engine.fContextPath = fContextPath.copy();
engine.fErrorPrintStream = fErrorPrintStream;
engine.fEvalLHSMode = fEvalLHSMode;
Expand Down Expand Up @@ -407,34 +404,41 @@ public EvalEngine copy() {
}

public void begin(String contextName) {
fContextPathStack.push(fContextPath);
fContextPath = fContextPath.copy();
Context packageContext = fContextPath.getContext(contextName);
setContext(packageContext);
}

public void beginPackage(String contextName) {
fContextPathStack.push(fContextPath);
Context packageContext = fContextPath.getContext(contextName);
setContextPath(new ContextPath(packageContext));
setContext(packageContext);
}

public Context end() {
Context packageContext = fContext;
setContext(fContextPath.last());
return packageContext;
if (fContextPathStack.size() > 0) {
ContextPath p = fContextPath;
Context c = fContextPath.currentContext();
fContextPath = fContextPathStack.pop();
fContextPath.synchronize(p);
return c;
}
return null;
}

public void endPackage() {
if (fContextPathStack.size() > 0) {
ContextPath p = fContextPath;
Context c = fContextPath.currentContext();
fContextPath = fContextPathStack.pop();
fContextPath.add(0, fContext);
fContext = fContextPath.last();
fContextPath.synchronize(p);
fContextPath.add(0, c);
}
}

public void cancel() {
fLocalVariableStackMap = null;
fContext = Context.SYSTEM;
fContextPath = null;
fErrorPrintStream = null;
fFileSystemEnabled = false;
Expand Down Expand Up @@ -1768,7 +1772,7 @@ public IAssumptions getAssumptions() {
}

public final Context getContext() {
return fContext;
return fContextPath.currentContext();
}

public ContextPath getContextPath() {
Expand Down Expand Up @@ -1882,8 +1886,7 @@ final public void init() {
fSeconds = 0;
fModifiedVariablesList = null;
fContextPathStack = new Stack<ContextPath>();
fContextPath = new ContextPath();
fContext = fContextPath.last();
fContextPath = ContextPath.initialContext();
fLocalVariableStackMap = null;
REMEMBER_AST_CACHE = null;
}
Expand Down Expand Up @@ -2107,7 +2110,7 @@ public void setContextPath(ContextPath contextPath) {
}

public void setContext(Context context) {
this.fContext = context;
this.fContextPath.setCurrentContext(context);
}

public void setErrorPrintStream(final PrintStream errorPrintStream) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

Expand All @@ -12,43 +11,33 @@
import org.matheclipse.core.interfaces.IStringX;
import org.matheclipse.core.interfaces.ISymbol;

public class ContextPath {
public final Map<String, Context> fContextMap;
List<Context> path = new ArrayList<Context>();
public final class ContextPath {
private HashMap<String, Context> fContextMap;
private ArrayList<Context> path = new ArrayList<Context>();
private Context fContext;

private ContextPath(List<Context> path) {
fContextMap = new HashMap<String, Context>(17);
this.path.add(Context.SYSTEM);
this.fContextMap.put(Context.SYSTEM.getContextName(), Context.SYSTEM);
// don't put RUBI on the context path
fContextMap.put(Context.RUBI.getContextName(), Context.RUBI);
// fContextMap.put(Context.DUMMY.getContextName(), Context.DUMMY);
for (int i = 1; i < path.size(); i++) {
// Start at index 1 because SYSTEM is already set!
this.path.add(path.get(i).copy());
}
private ContextPath() {
// for copy() method
}

public ContextPath() {
fContextMap = new HashMap<String, Context>(17);
path.add(Context.SYSTEM);
fContextMap.put(Context.SYSTEM.getContextName(), Context.SYSTEM);
/**
* Get the initial context(s) for an evaluation engine.
*
* @return
*/
public static ContextPath initialContext() {
ContextPath cp = new ContextPath();
cp.fContextMap = new HashMap<String, Context>(17);
cp.path.add(Context.SYSTEM);
cp.fContextMap.put(Context.SYSTEM.getContextName(), Context.SYSTEM);
// don't put RUBI on the context path
fContextMap.put(Context.RUBI.getContextName(), Context.RUBI);
cp.fContextMap.put(Context.RUBI.getContextName(), Context.RUBI);
// fContextMap.put(Context.DUMMY.getContextName(), Context.DUMMY);
Context global = new Context(Context.GLOBAL_CONTEXT_NAME);
path.add(global);
fContextMap.put(Context.GLOBAL_CONTEXT_NAME, global);
}

public ContextPath(String contextName) {
fContextMap = new HashMap<String, Context>(17);
path.add(getContext(contextName));
path.add(Context.SYSTEM);
fContextMap.put(Context.SYSTEM.getContextName(), Context.SYSTEM);
// don't put RUBI on the context path
fContextMap.put(Context.RUBI.getContextName(), Context.RUBI);
// fContextMap.put(Context.DUMMY.getContextName(), Context.DUMMY);
cp.path.add(global);
cp.fContextMap.put(Context.GLOBAL_CONTEXT_NAME, global);
cp.fContext = global;
return cp;
}

public ContextPath(Context context) {
Expand All @@ -59,23 +48,19 @@ public ContextPath(Context context) {
// don't put RUBI on the context path
fContextMap.put(Context.RUBI.getContextName(), Context.RUBI);
// fContextMap.put(Context.DUMMY.getContextName(), Context.DUMMY);

fContext = context;
}

public ContextPath copy() {
return new ContextPath(path);
ContextPath cp = new ContextPath();
cp.fContextMap = (HashMap<String, Context>) fContextMap.clone();
cp.path = (ArrayList<Context>) path.clone();
cp.fContext = fContext;
return cp;
}

public Context getGlobalContext() {
int size = path.size();
int start = size - 1;
for (int i = start; i >= 0; i--) {
Context temp = path.get(i);
if (temp.getContextName().equals(Context.GLOBAL_CONTEXT_NAME)) {
return temp;
}
}
return null;
return fContextMap.get(Context.GLOBAL_CONTEXT_NAME);
}

/**
Expand All @@ -94,9 +79,16 @@ public IAST pathAsStrings() {
return result;
}

public IStringX currentContext() {
int size = path.size() - 1;
return F.stringx(path.get(size).getContextName());
public IStringX currentContextString() {
return F.stringx(fContext.getContextName());
}

public Context currentContext() {
return fContext;
}

public void setCurrentContext(Context context) {
fContext = context;
}

public boolean setGlobalContext(Context context) {
Expand Down Expand Up @@ -138,10 +130,6 @@ public Context get(int index) {
return path.get(index);
}

public Context last() {
return path.get(path.size() - 1);
}

public ISymbol symbol(String symbolName, Context newContext, boolean relaxedSyntax) {
String name = symbolName;
if (relaxedSyntax) {
Expand All @@ -160,12 +148,12 @@ public ISymbol symbol(String symbolName, Context newContext, boolean relaxedSynt
return symbol;
}
}

symbol = newContext.get(name);
if (symbol != null) {
return symbol;
}

symbol = new Symbol(name, newContext);
newContext.put(name, symbol);
// engine.putUserVariable(name, symbol);
Expand Down Expand Up @@ -233,6 +221,24 @@ public Context remove(int index) {
return path.remove(index);
}

/**
* Synchronize the contexts back to this context map.
*
* @param path
* @return
*/
public void synchronize(ContextPath path) {
Context c = path.fContext;
if (!fContextMap.containsKey(c.getContextName())) {
fContextMap.put(c.getContextName(), c);
}
for (Map.Entry<String, Context> entry : path.fContextMap.entrySet()) {
if (!fContextMap.containsKey(entry.getKey())) {
fContextMap.put(entry.getKey(), entry.getValue());
}
}
}

public Context set(int index, Context element) {
return path.set(index, element);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,44 @@ public void testBeginPackage() {
"144");
}

public void testBeginPackageNested() {
check("BeginPackage(\"test`\")", //
"");
check("Context( )", //
"test`");
check("$ContextPath", //
"{test`,System`}");
check("testit::usage = \"testit(x) gives x^2\"", //
"testit(x) gives x^2");
check("testit(x_) := x^2 ", //
"");
check("Begin(\"test`Private`\")", //
"");
check("test2(x_) := x^3 ", //
"");
check("testit(12)", //
"144");
check("End( )", //
"test`Private`");
check("$ContextPath", //
"{test`,System`}");
check("Context( )", //
"test`");
check("EndPackage( )", //
"");
check("test`Private`test2(12)", //
"1728");
check("$ContextPath", //
"{test`,System`,Global`}");
check("Context( )", //
"Global`");
// print usage message in console
check("?testit", //
"");
check("testit(12)", //
"144");
}

public void testBegin() {
check("Begin(\"mytest`\")", //
"");
Expand Down

0 comments on commit d5a1bf9

Please sign in to comment.