muScript: support globals

This commit is contained in:
Johannes Frohnmeyer 2023-03-11 14:07:33 +01:00
parent a5fa86a6c7
commit 044f468024
Signed by: Johannes
GPG Key ID: E76429612C2929F4
2 changed files with 71 additions and 4 deletions

View File

@ -2,24 +2,37 @@ package io.gitlab.jfronny.muscript.data;
import io.gitlab.jfronny.commons.data.ImmCollection;
import io.gitlab.jfronny.muscript.data.dynamic.*;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Function;
public class Scope implements DObject {
private final DObject source;
private final @Nullable Scope source;
private final Map<String, Dynamic<?>> override = new HashMap<>();
public Scope() {
this(DFinal.of(Map.of()));
this(null);
}
public Scope(DObject source) {
public Scope(@Nullable DObject source) {
if (source == null) {
this.source = null;
} else if (source instanceof Scope src) {
this.source = src;
} else {
this.source = new Scope();
source.getValue().forEach(this::set);
}
}
public Scope(@Nullable Scope source) {
this.source = source;
}
@Override
public Map<String, Dynamic<?>> getValue() {
if (source == null) return ImmCollection.of(override);
var map = new HashMap<>(source.getValue());
map.putAll(override);
return ImmCollection.of(map);
@ -30,10 +43,25 @@ public class Scope implements DObject {
*/
@Deprecated(forRemoval = false)
public Scope set(String key, Dynamic<?> value) {
override.put(key, value);
if (key.startsWith("$")) {
if (!setGlobal(key, value)) override.put(key, value);
} else {
override.put(key, value);
}
return this;
}
private boolean setGlobal(String key, Dynamic<?> value) {
if (override.containsKey(key)) {
override.put(key, value);
return true;
} else if (source != null) {
return source.setGlobal(key, value);
} else {
return false;
}
}
public Scope set(String key, boolean value) {
return set(key, DFinal.of(value));
}

View File

@ -0,0 +1,39 @@
package io.gitlab.jfronny.muscript.test;
import io.gitlab.jfronny.muscript.compiler.Parser;
import io.gitlab.jfronny.muscript.error.LocationalException;
import org.junit.jupiter.api.Test;
import static io.gitlab.jfronny.muscript.test.util.MuTestUtil.makeArgs;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class GlobalTest {
@Test
void notAll() {
assertEquals(12, Parser.parseScript("""
v = 12
{->v = 5}()
v
""").run(makeArgs()).asNumber().getValue());
}
@Test
void global() {
assertEquals(5, Parser.parseScript("""
$v = 12
{->$v = 5}()
$v
""").run(makeArgs()).asNumber().getValue());
}
@Test
void innermost() {
assertThrows(LocationalException.class,
() -> Parser.parseScript("""
{->$v = 12}()
$v
""").run(makeArgs()).asNumber().getValue(),
"This object doesn't contain '$v'");
}
}