Define functions and constants in root scope

This commit is contained in:
aNNiMON 2023-09-03 21:42:23 +03:00 committed by Victor Melnik
parent 16de63f720
commit fe39c1ac00
15 changed files with 344 additions and 188 deletions

View File

@ -1,7 +1,5 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import com.annimon.ownlang.exceptions.UnknownFunctionException;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -9,32 +7,21 @@ import java.util.Map;
* @author aNNiMON * @author aNNiMON
*/ */
public final class Functions { public final class Functions {
private static final Map<String, Function> functions;
static {
functions = new HashMap<>();
}
private Functions() { } private Functions() { }
public static void clear() {
functions.clear();
}
public static Map<String, Function> getFunctions() { public static Map<String, Function> getFunctions() {
return functions; return ScopeHandler.functions();
} }
public static boolean isExists(String key) { public static boolean isExists(String name) {
return functions.containsKey(key); return ScopeHandler.isFunctionExists(name);
} }
public static Function get(String key) { public static Function get(String name) {
if (!isExists(key)) throw new UnknownFunctionException(key); return ScopeHandler.getFunction(name);
return functions.get(key);
} }
public static void set(String key, Function function) { public static void set(String key, Function function) {
functions.put(key, function); ScopeHandler.setFunction(key, function);
} }
} }

View File

@ -0,0 +1,68 @@
package com.annimon.ownlang.lib;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
final class RootScope extends Scope {
private final Map<String, Value> constants;
private final Map<String, Function> functions;
RootScope() {
functions = new ConcurrentHashMap<>();
constants = new ConcurrentHashMap<>();
constants.put("true", NumberValue.ONE);
constants.put("false", NumberValue.ZERO);
}
@Override
public boolean isRoot() {
return true;
}
@Override
public boolean contains(String name) {
return super.containsVariable(name)
|| containsConstant(name);
}
public boolean containsConstant(String name) {
return constants.containsKey(name);
}
@Override
public Value get(String name) {
if (containsConstant(name)) {
return getConstant(name);
}
return super.get(name);
}
public Value getConstant(String name) {
return constants.get(name);
}
public void setConstant(String name, Value value) {
constants.put(name, value);
}
public Map<String, Value> getConstants() {
return constants;
}
public boolean containsFunction(String name) {
return functions.containsKey(name);
}
public Function getFunction(String name) {
return functions.get(name);
}
public void setFunction(String name, Function function) {
functions.put(name, function);
}
public Map<String, Function> getFunctions() {
return functions;
}
}

View File

@ -0,0 +1,64 @@
package com.annimon.ownlang.lib;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
sealed class Scope permits RootScope {
final Scope parent;
private final Map<String, Value> variables;
Scope() {
this(null);
}
Scope(Scope parent) {
this.parent = parent;
variables = new ConcurrentHashMap<>();
}
public boolean isRoot() {
return !hasParent();
}
public boolean hasParent() {
return parent != null;
}
public boolean contains(String name) {
return containsVariable(name);
}
public final boolean containsVariable(String name) {
return variables.containsKey(name);
}
public Value get(String name) {
return getVariable(name);
}
public final Value getVariable(String name) {
return variables.get(name);
}
public final void setVariable(String name, Value value) {
variables.put(name, value);
}
public final void removeVariable(String name) {
variables.remove(name);
}
public Map<String, Value> getVariables() {
return variables;
}
static class ScopeFindData {
final boolean isFound;
final Scope scope;
ScopeFindData(boolean isFound, Scope scope) {
this.isFound = isFound;
this.scope = scope;
}
}
}

View File

@ -0,0 +1,129 @@
package com.annimon.ownlang.lib;
import com.annimon.ownlang.exceptions.UnknownFunctionException;
import com.annimon.ownlang.lib.Scope.ScopeFindData;
import java.util.Map;
public final class ScopeHandler {
private static final Object lock = new Object();
private static volatile RootScope rootScope;
private static volatile Scope scope;
static {
ScopeHandler.resetScope();
}
public static Map<String, Value> variables() {
return scope.getVariables();
}
public static Map<String, Value> constants() {
return rootScope.getConstants();
}
public static Map<String, Function> functions() {
return rootScope.getFunctions();
}
/**
* Resets a scope for new program execution
*/
public static void resetScope() {
rootScope = new RootScope();
scope = rootScope;
}
public static void push() {
synchronized (lock) {
scope = new Scope(scope);
}
}
public static void pop() {
synchronized (lock) {
if (!scope.isRoot()) {
scope = scope.parent;
}
}
}
public static boolean isFunctionExists(String name) {
return rootScope.containsFunction(name);
}
public static Function getFunction(String name) {
final var function = rootScope.getFunction(name);
if (function == null) throw new UnknownFunctionException(name);
return function;
}
public static void setFunction(String name, Function function) {
rootScope.setFunction(name, function);
}
public static boolean isVariableOrConstantExists(String name) {
synchronized (lock) {
return findScope(name).isFound;
}
}
public static Value getVariableOrConstant(String name) {
synchronized (lock) {
final ScopeFindData scopeData = findScope(name);
if (scopeData.isFound) {
return scopeData.scope.get(name);
}
}
return NumberValue.ZERO;
}
public static Value getVariable(String name) {
synchronized (lock) {
final ScopeFindData scopeData = findScope(name);
if (scopeData.isFound) {
return scopeData.scope.getVariable(name);
}
}
// TODO should be strict
return NumberValue.ZERO;
}
public static void setVariable(String name, Value value) {
synchronized (lock) {
findScope(name).scope.setVariable(name, value);
}
}
public static void setConstant(String name, Value value) {
rootScope.setConstant(name, value);
}
public static void defineVariableInCurrentScope(String name, Value value) {
synchronized (lock) {
scope.setVariable(name, value);
}
}
public static void removeVariable(String name) {
synchronized (lock) {
findScope(name).scope.removeVariable(name);
}
}
private static ScopeFindData findScope(String name) {
Scope current = scope;
do {
if (current.contains(name)) {
return new ScopeFindData(true, current);
}
} while ((current = current.parent) != null);
return new ScopeFindData(false, scope);
}
}

View File

@ -1,118 +1,34 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class Variables { public final class Variables {
private static final Object lock = new Object();
private static class Scope {
final Scope parent;
final Map<String, Value> variables;
Scope() {
this(null);
}
Scope(Scope parent) {
this.parent = parent;
variables = new ConcurrentHashMap<>();
}
}
private static class ScopeFindData {
boolean isFound;
Scope scope;
}
private static volatile Scope scope;
static {
Variables.clear();
}
private Variables() { } private Variables() { }
public static Map<String, Value> variables() { public static Map<String, Value> variables() {
return scope.variables; return ScopeHandler.variables();
} }
public static void clear() { public static boolean isExists(String name) {
scope = new Scope(); return ScopeHandler.isVariableOrConstantExists(name);
scope.variables.clear();
scope.variables.put("true", NumberValue.ONE);
scope.variables.put("false", NumberValue.ZERO);
} }
public static void push() { public static Value get(String name) {
synchronized (lock) { return ScopeHandler.getVariableOrConstant(name);
scope = new Scope(scope);
}
} }
public static void pop() { public static void set(String name, Value value) {
synchronized (lock) { ScopeHandler.setVariable(name, value);
if (scope.parent != null) {
scope = scope.parent;
}
}
} }
public static boolean isExists(String key) { /**
synchronized (lock) { * For compatibility with other modules
return findScope(key).isFound;
}
}
public static Value get(String key) {
synchronized (lock) {
final ScopeFindData scopeData = findScope(key);
if (scopeData.isFound) {
return scopeData.scope.variables.get(key);
}
}
return NumberValue.ZERO;
}
public static void set(String key, Value value) {
synchronized (lock) {
findScope(key).scope.variables.put(key, value);
}
}
public static void define(String key, Value value) {
synchronized (lock) {
scope.variables.put(key, value);
}
}
public static void remove(String key) {
synchronized (lock) {
findScope(key).scope.variables.remove(key);
}
}
/*
* Find scope where variable exists.
*/ */
private static ScopeFindData findScope(String variable) { public static void define(String name, Value value) {
final ScopeFindData result = new ScopeFindData(); ScopeHandler.setConstant(name, value);
Scope current = scope;
do {
if (current.variables.containsKey(variable)) {
result.isFound = true;
result.scope = current;
return result;
}
} while ((current = current.parent) != null);
result.isFound = false;
result.scope = scope;
return result;
} }
} }

View File

@ -14,13 +14,13 @@ public class ClassMethod extends UserDefinedFunction {
@Override @Override
public Value execute(Value[] values) { public Value execute(Value[] values) {
Variables.push(); ScopeHandler.push();
Variables.define("this", classInstance.getThisMap()); ScopeHandler.defineVariableInCurrentScope("this", classInstance.getThisMap());
try { try {
return super.execute(values); return super.execute(values);
} finally { } finally {
Variables.pop(); ScopeHandler.pop();
} }
} }
} }

View File

@ -45,21 +45,21 @@ public class UserDefinedFunction implements Function {
} }
try { try {
Variables.push(); ScopeHandler.push();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Variables.define(getArgsName(i), values[i]); ScopeHandler.defineVariableInCurrentScope(getArgsName(i), values[i]);
} }
// Optional args if exists // Optional args if exists
for (int i = size; i < totalArgsCount; i++) { for (int i = size; i < totalArgsCount; i++) {
final Argument arg = arguments.get(i); final Argument arg = arguments.get(i);
Variables.define(arg.name(), arg.valueExpr().eval()); ScopeHandler.defineVariableInCurrentScope(arg.name(), arg.valueExpr().eval());
} }
body.execute(); body.execute();
return NumberValue.ZERO; return NumberValue.ZERO;
} catch (ReturnStatement rt) { } catch (ReturnStatement rt) {
return rt.getResult(); return rt.getResult();
} finally { } finally {
Variables.pop(); ScopeHandler.pop();
} }
} }

View File

@ -1,13 +1,12 @@
package com.annimon.ownlang.parser; package com.annimon.ownlang.parser;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.parser.linters.AssignValidator; import com.annimon.ownlang.lib.ScopeHandler;
import com.annimon.ownlang.parser.linters.UseWithNonStringValueValidator;
import com.annimon.ownlang.parser.linters.DefaultFunctionsOverrideValidator;
import com.annimon.ownlang.lib.Functions;
import com.annimon.ownlang.lib.Variables;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.Visitor; import com.annimon.ownlang.parser.ast.Visitor;
import com.annimon.ownlang.parser.linters.AssignValidator;
import com.annimon.ownlang.parser.linters.DefaultFunctionsOverrideValidator;
import com.annimon.ownlang.parser.linters.UseWithNonStringValueValidator;
public final class Linter { public final class Linter {
@ -36,7 +35,6 @@ public final class Linter {
} }
private void resetState() { private void resetState() {
Variables.clear(); ScopeHandler.resetScope();
Functions.getFunctions().clear();
} }
} }

View File

@ -1,10 +1,7 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -42,7 +39,7 @@ public final class DestructuringAssignmentStatement extends InterruptableNode im
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final String variable = variables.get(i); final String variable = variables.get(i);
if (variable != null) { if (variable != null) {
Variables.define(variable, array.get(i)); ScopeHandler.defineVariableInCurrentScope(variable, array.get(i));
} }
} }
} }
@ -51,7 +48,7 @@ public final class DestructuringAssignmentStatement extends InterruptableNode im
for (Map.Entry<Value, Value> entry : map) { for (Map.Entry<Value, Value> entry : map) {
final String variable = variables.get(i); final String variable = variables.get(i);
if (variable != null) { if (variable != null) {
Variables.define(variable, new ArrayValue( ScopeHandler.defineVariableInCurrentScope(variable, new ArrayValue(
new Value[] { entry.getKey(), entry.getValue() } new Value[] { entry.getKey(), entry.getValue() }
)); ));
} }

View File

@ -23,7 +23,8 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
@Override @Override
public void execute() { public void execute() {
super.interruptionCheck(); super.interruptionCheck();
final Value previousVariableValue = Variables.isExists(variable) ? Variables.get(variable) : null; // TODO removing without checking shadowing is dangerous
final Value previousVariableValue = ScopeHandler.getVariable(variable);
final Value containerValue = container.eval(); final Value containerValue = container.eval();
switch (containerValue.type()) { switch (containerValue.type()) {
@ -42,15 +43,15 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
// Restore variables // Restore variables
if (previousVariableValue != null) { if (previousVariableValue != null) {
Variables.set(variable, previousVariableValue); ScopeHandler.setVariable(variable, previousVariableValue);
} else { } else {
Variables.remove(variable); ScopeHandler.removeVariable(variable);
} }
} }
private void iterateString(String str) { private void iterateString(String str) {
for (char ch : str.toCharArray()) { for (char ch : str.toCharArray()) {
Variables.set(variable, new StringValue(String.valueOf(ch))); ScopeHandler.setVariable(variable, new StringValue(String.valueOf(ch)));
try { try {
body.execute(); body.execute();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
@ -63,7 +64,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
private void iterateArray(ArrayValue containerValue) { private void iterateArray(ArrayValue containerValue) {
for (Value value : containerValue) { for (Value value : containerValue) {
Variables.set(variable, value); ScopeHandler.setVariable(variable, value);
try { try {
body.execute(); body.execute();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
@ -76,7 +77,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
private void iterateMap(MapValue containerValue) { private void iterateMap(MapValue containerValue) {
for (Map.Entry<Value, Value> entry : containerValue) { for (Map.Entry<Value, Value> entry : containerValue) {
Variables.set(variable, new ArrayValue(new Value[] { ScopeHandler.setVariable(variable, new ArrayValue(new Value[] {
entry.getKey(), entry.getKey(),
entry.getValue() entry.getValue()
})); }));

View File

@ -24,8 +24,9 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
@Override @Override
public void execute() { public void execute() {
super.interruptionCheck(); super.interruptionCheck();
final Value previousVariableValue1 = Variables.isExists(key) ? Variables.get(key) : null; // TODO removing without checking shadowing is dangerous
final Value previousVariableValue2 = Variables.isExists(value) ? Variables.get(value) : null; final Value previousVariableValue1 = ScopeHandler.getVariable(key);
final Value previousVariableValue2 = ScopeHandler.getVariable(value);
final Value containerValue = container.eval(); final Value containerValue = container.eval();
switch (containerValue.type()) { switch (containerValue.type()) {
@ -44,21 +45,21 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
// Restore variables // Restore variables
if (previousVariableValue1 != null) { if (previousVariableValue1 != null) {
Variables.set(key, previousVariableValue1); ScopeHandler.setVariable(key, previousVariableValue1);
} else { } else {
Variables.remove(key); ScopeHandler.removeVariable(key);
} }
if (previousVariableValue2 != null) { if (previousVariableValue2 != null) {
Variables.set(value, previousVariableValue2); ScopeHandler.setVariable(value, previousVariableValue2);
} else { } else {
Variables.remove(value); ScopeHandler.removeVariable(value);
} }
} }
private void iterateString(String str) { private void iterateString(String str) {
for (char ch : str.toCharArray()) { for (char ch : str.toCharArray()) {
Variables.set(key, new StringValue(String.valueOf(ch))); ScopeHandler.setVariable(key, new StringValue(String.valueOf(ch)));
Variables.set(value, NumberValue.of(ch)); ScopeHandler.setVariable(value, NumberValue.of(ch));
try { try {
body.execute(); body.execute();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
@ -72,8 +73,8 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
private void iterateArray(ArrayValue containerValue) { private void iterateArray(ArrayValue containerValue) {
int index = 0; int index = 0;
for (Value v : containerValue) { for (Value v : containerValue) {
Variables.set(key, v); ScopeHandler.setVariable(key, v);
Variables.set(value, NumberValue.of(index++)); ScopeHandler.setVariable(value, NumberValue.of(index++));
try { try {
body.execute(); body.execute();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
@ -86,8 +87,8 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
private void iterateMap(MapValue containerValue) { private void iterateMap(MapValue containerValue) {
for (Map.Entry<Value, Value> entry : containerValue) { for (Map.Entry<Value, Value> entry : containerValue) {
Variables.set(key, entry.getKey()); ScopeHandler.setVariable(key, entry.getKey());
Variables.set(value, entry.getValue()); ScopeHandler.setVariable(value, entry.getValue());
try { try {
body.execute(); body.execute();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {

View File

@ -64,11 +64,11 @@ public final class FunctionalExpression extends InterruptableNode implements Exp
} }
private Function getFunction(String key) { private Function getFunction(String key) {
if (Functions.isExists(key)) { if (ScopeHandler.isFunctionExists(key)) {
return Functions.get(key); return ScopeHandler.getFunction(key);
} }
if (Variables.isExists(key)) { if (ScopeHandler.isVariableOrConstantExists(key)) {
final Value variable = Variables.get(key); final Value variable = ScopeHandler.getVariableOrConstant(key);
if (variable.type() == Types.FUNCTION) { if (variable.type() == Types.FUNCTION) {
return ((FunctionValue)variable).getValue(); return ((FunctionValue)variable).getValue();
} }

View File

@ -1,11 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.exceptions.PatternMatchingException; import com.annimon.ownlang.exceptions.PatternMatchingException;
import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -44,18 +41,18 @@ public final class MatchExpression extends InterruptableNode implements Expressi
final VariablePattern pattern = (VariablePattern) p; final VariablePattern pattern = (VariablePattern) p;
if (pattern.variable.equals("_")) return evalResult(p.result); if (pattern.variable.equals("_")) return evalResult(p.result);
if (Variables.isExists(pattern.variable)) { if (ScopeHandler.isVariableOrConstantExists(pattern.variable)) {
if (match(value, Variables.get(pattern.variable)) && optMatches(p)) { if (match(value, ScopeHandler.getVariableOrConstant(pattern.variable)) && optMatches(p)) {
return evalResult(p.result); return evalResult(p.result);
} }
} else { } else {
Variables.define(pattern.variable, value); ScopeHandler.defineVariableInCurrentScope(pattern.variable, value);
if (optMatches(p)) { if (optMatches(p)) {
final Value result = evalResult(p.result); final Value result = evalResult(p.result);
Variables.remove(pattern.variable); ScopeHandler.removeVariable(pattern.variable);
return result; return result;
} }
Variables.remove(pattern.variable); ScopeHandler.removeVariable(pattern.variable);
} }
} }
if ((value.type() == Types.ARRAY) && (p instanceof ListPattern)) { if ((value.type() == Types.ARRAY) && (p instanceof ListPattern)) {
@ -64,7 +61,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
// Clean up variables if matched // Clean up variables if matched
final Value result = evalResult(p.result); final Value result = evalResult(p.result);
for (String var : pattern.parts) { for (String var : pattern.parts) {
Variables.remove(var); ScopeHandler.removeVariable(var);
} }
return result; return result;
} }
@ -105,11 +102,11 @@ public final class MatchExpression extends InterruptableNode implements Expressi
case 1: // match arr { case [x]: x = arr ... } case 1: // match arr { case [x]: x = arr ... }
final String variable = parts.get(0); final String variable = parts.get(0);
Variables.define(variable, array); ScopeHandler.defineVariableInCurrentScope(variable, array);
if (optMatches(p)) { if (optMatches(p)) {
return true; return true;
} }
Variables.remove(variable); ScopeHandler.removeVariable(variable);
return false; return false;
default: { // match arr { case [...]: .. } default: { // match arr { case [...]: .. }
@ -128,7 +125,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
private boolean matchListPatternEqualsSize(ListPattern p, List<String> parts, int partsSize, ArrayValue array) { private boolean matchListPatternEqualsSize(ListPattern p, List<String> parts, int partsSize, ArrayValue array) {
// Set variables // Set variables
for (int i = 0; i < partsSize; i++) { for (int i = 0; i < partsSize; i++) {
Variables.define(parts.get(i), array.get(i)); ScopeHandler.defineVariableInCurrentScope(parts.get(i), array.get(i));
} }
if (optMatches(p)) { if (optMatches(p)) {
// Clean up will be provided after evaluate result // Clean up will be provided after evaluate result
@ -136,7 +133,8 @@ public final class MatchExpression extends InterruptableNode implements Expressi
} }
// Clean up variables if no match // Clean up variables if no match
for (String var : parts) { for (String var : parts) {
Variables.remove(var); // TODO removing without checking shadowing is dangerous
ScopeHandler.removeVariable(var);
} }
return false; return false;
} }
@ -145,14 +143,14 @@ public final class MatchExpression extends InterruptableNode implements Expressi
// Set element variables // Set element variables
final int lastPart = partsSize - 1; final int lastPart = partsSize - 1;
for (int i = 0; i < lastPart; i++) { for (int i = 0; i < lastPart; i++) {
Variables.define(parts.get(i), array.get(i)); ScopeHandler.defineVariableInCurrentScope(parts.get(i), array.get(i));
} }
// Set tail variable // Set tail variable
final ArrayValue tail = new ArrayValue(arraySize - partsSize + 1); final ArrayValue tail = new ArrayValue(arraySize - partsSize + 1);
for (int i = lastPart; i < arraySize; i++) { for (int i = lastPart; i < arraySize; i++) {
tail.set(i - lastPart, array.get(i)); tail.set(i - lastPart, array.get(i));
} }
Variables.define(parts.get(lastPart), tail); ScopeHandler.defineVariableInCurrentScope(parts.get(lastPart), tail);
// Check optional condition // Check optional condition
if (optMatches(p)) { if (optMatches(p)) {
// Clean up will be provided after evaluate result // Clean up will be provided after evaluate result
@ -160,7 +158,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
} }
// Clean up variables // Clean up variables
for (String var : parts) { for (String var : parts) {
Variables.remove(var); ScopeHandler.removeVariable(var);
} }
return false; return false;
} }

View File

@ -1,6 +1,7 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.exceptions.VariableDoesNotExistsException; import com.annimon.ownlang.exceptions.VariableDoesNotExistsException;
import com.annimon.ownlang.lib.ScopeHandler;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
@ -30,7 +31,7 @@ public final class VariableExpression extends InterruptableNode implements Expre
@Override @Override
public Value set(Value value) { public Value set(Value value) {
Variables.set(name, value); ScopeHandler.setVariable(name, value);
return value; return value;
} }

View File

@ -1,10 +1,7 @@
package com.annimon.ownlang.parser; package com.annimon.ownlang.parser;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.FunctionValue; import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.lib.Functions;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Variables;
import com.annimon.ownlang.outputsettings.OutputSettings; import com.annimon.ownlang.outputsettings.OutputSettings;
import com.annimon.ownlang.outputsettings.StringOutputSettings; import com.annimon.ownlang.outputsettings.StringOutputSettings;
import com.annimon.ownlang.parser.ast.FunctionDefineStatement; import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
@ -33,8 +30,7 @@ public class ProgramsTest {
@BeforeEach @BeforeEach
public void initialize() { public void initialize() {
Variables.clear(); ScopeHandler.resetScope();
Functions.clear();
// Let's mock junit methods as ounit functions // Let's mock junit methods as ounit functions
Functions.set("assertEquals", (args) -> { Functions.set("assertEquals", (args) -> {
assertEquals(args[0], args[1]); assertEquals(args[0], args[1]);