Skip to content

Commit

Permalink
Construct variables for scripts
Browse files Browse the repository at this point in the history
This allows scripts to be used as values.
  • Loading branch information
rubensworks committed Dec 18, 2023
1 parent 8a96656 commit f1fd9e5
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import net.minecraft.network.chat.Style;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integratedscripting.api.network.IScriptFactory;

import java.util.List;

Expand All @@ -17,4 +19,6 @@ public interface ILanguageHandler {

public List<Pair<Style, String>> markupLine(String line);

public IScriptFactory getScriptFactory() throws EvaluationException;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.cyclops.integratedscripting.api.network;

import javax.annotation.Nullable;

/**
* A script that contains executable members.
* @author rubensworks
*/
public interface IScript {

/**
* Get the given script member.
* @param memberName A member name.
* @return The member, or null if it does not exist.
*/
@Nullable
public IScriptMember getMember(String memberName);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.cyclops.integratedscripting.api.network;

import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;

import javax.annotation.Nullable;
import java.nio.file.Path;

/**
* Instantiates scripts for paths in disks.
* @author rubensworks
*/
public interface IScriptFactory {

/**
* Get the script by the given path in the given disk.
* @param disk A disk id.
* @param path A script path.
* @return The script or null.
*/
@Nullable
public IScript getScript(int disk, Path path) throws EvaluationException;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.cyclops.integratedscripting.api.network;

import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;

/**
* A script member that contains a value.
* @author rubensworks
*/
public interface IScriptMember {

/**
* @return The member value as Integrated Dynamics value.
* @throws EvaluationException If an error occurred.
*/
public IValue getValue() throws EvaluationException;

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.cyclops.integratedscripting.api.network;


import javax.annotation.Nullable;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;

/**
* Capability for handling scripts inside a world.
* Server-side singleton for handling scripts inside the game.
* @see {@link IntegratedScripting#scriptingData}
* @author rubensworks
*/
public interface IScriptingData {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.cyclops.integratedscripting.api.network;

import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
import org.cyclops.integrateddynamics.api.evaluate.variable.IVariable;

import javax.annotation.Nullable;
import java.nio.file.Path;
import java.util.Set;

/**
Expand All @@ -8,10 +14,41 @@
*/
public interface IScriptingNetwork {

/**
* Indicate that the given disk is contained in this network.
* @param disk A disk id.
*/
public void addDisk(int disk);

/**
* Indicate that the given disk is not contained in this network.
* @param disk A disk id.
*/
public void removeDisk(int disk);

/**
* @return All disks contained in this network.
*/
public Set<Integer> getDisks();

/**
* Get the script by the given path in the given disk.
* @param disk A disk id.
* @param path A script path.
* @return The script or null.
*/
@Nullable
public IScript getScript(int disk, Path path) throws EvaluationException;

/**
* Get a variable containing the value of the given script member.
* This variable can be cached and invalidated if the underlying script is modified.
* @param disk A disk id.
* @param path A script path.
* @param member A script member name.
* @param <V> The value type.
* @return A variable.
*/
public <V extends IValue> IVariable<V> getOrCreateVariable(int disk, Path path, String member);

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.data.ModelData;
import org.cyclops.integrateddynamics.api.client.model.IVariableModelBaked;
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueType;
import org.cyclops.integrateddynamics.api.evaluate.variable.IVariable;
import org.cyclops.integrateddynamics.api.network.INetwork;
import org.cyclops.integrateddynamics.api.network.IPartNetwork;
import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes;
import org.cyclops.integrateddynamics.core.helper.L10NValues;
import org.cyclops.integrateddynamics.core.item.VariableFacadeBase;
import org.cyclops.integratedscripting.api.item.IScriptVariableFacade;
import org.cyclops.integratedscripting.api.network.IScriptingNetwork;
import org.cyclops.integratedscripting.core.client.model.ScriptingVariableModelProviders;
import org.cyclops.integratedscripting.core.network.ScriptingNetworkHelpers;

import java.nio.file.Path;
import java.util.List;
Expand Down Expand Up @@ -49,11 +54,11 @@ public ScriptVariableFacade(int id, int disk, Path path, String member) {
}

@Override
public <V extends IValue> IVariable<V> getVariable(IPartNetwork network) {
public <V extends IValue> IVariable<V> getVariable(INetwork network, IPartNetwork partNetwork) {
if(isValid()) {
// TODO: get variable of script from scripting network
// IVariable<V> variable = getTargetVariable(network).orElse(null);
// return variable;
return ScriptingNetworkHelpers.getScriptingNetwork(network)
.map(scriptingNetwork -> scriptingNetwork.<V>getOrCreateVariable(this.disk, this.path, this.member))
.orElse(null);
}
return null;
}
Expand All @@ -64,21 +69,23 @@ public boolean isValid() {
}

@Override
public void validate(IPartNetwork network, IValidator validator, IValueType containingValueType) {
// TODO: validation: check if disk is present and such...
// Optional<IVariable> targetVariable = getTargetVariable(network);
// if (!isValid()) {
// validator.addError(Component.translatable(L10NValues.VARIABLE_ERROR_INVALIDITEM));
// } else if (network.getScript(proxyId) == null) {
// validator.addError(getScriptNotInNetworkError());
// } else if (!targetVariable.isPresent()) {
// validator.addError(getScriptInvalidError());
// } else if (!ValueHelpers.correspondsTo(containingValueType, targetVariable.get().getType())) {
// validator.addError(getScriptInvalidTypeError(network, containingValueType,
// targetVariable.get().getType()));
// }

getVariable(network);
public void validate(INetwork network, IPartNetwork partNetwork, IValidator validator, IValueType containingValueType) {
IScriptingNetwork scriptingNetwork = ScriptingNetworkHelpers.getScriptingNetwork(network).orElse(null);
try {
if (!isValid()) {
validator.addError(Component.translatable(L10NValues.VARIABLE_ERROR_INVALIDITEM));
} else if (scriptingNetwork == null) {
validator.addError(Component.translatable("script.integratedscripting.error.invalid_network"));
} else if (!scriptingNetwork.getDisks().contains(this.disk)) {
validator.addError(Component.translatable("script.integratedscripting.error.disk_not_in_network", this.disk));
} else if (scriptingNetwork.getScript(this.disk, this.path) == null) {
validator.addError(Component.translatable("script.integratedscripting.error.path_not_in_network", this.disk, this.path.toString()));
} else if (scriptingNetwork.getScript(this.disk, this.path).getMember(this.member) == null) {
validator.addError(Component.translatable("script.integratedscripting.error.member_not_in_network", this.disk, this.path.toString(), this.member));
}
} catch (EvaluationException e) {
validator.addError(e.getErrorMessage());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.cyclopscore.helper.Helpers;
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integratedscripting.api.language.ILanguageHandler;
import org.cyclops.integratedscripting.api.network.IScriptFactory;
import org.cyclops.integratedscripting.core.network.GraalScriptFactory;
import org.cyclops.integratedscripting.evaluate.ScriptHelpers;
import org.graalvm.polyglot.Context;

import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -89,4 +94,10 @@ public List<Pair<Style, String>> markupLine(String line) {

return segments;
}

@Override
public IScriptFactory getScriptFactory() throws EvaluationException {
Context context = ScriptHelpers.createPopulatedContext();
return new GraalScriptFactory(context, context.getBindings("js"), "js");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.collect.Maps;
import org.cyclops.integratedscripting.api.language.ILanguageHandler;
import org.cyclops.integratedscripting.api.language.ILanguageHandlerRegistry;
import org.cyclops.integratedscripting.evaluate.ScriptHelpers;

import javax.annotation.Nullable;
import java.nio.file.Path;
Expand Down Expand Up @@ -37,10 +38,8 @@ public void register(ILanguageHandler translator) {
@Nullable
@Override
public ILanguageHandler getProvider(Path filePath) {
String filePathString = filePath.toString();
int dotPos = filePathString.lastIndexOf('.');
if (dotPos >= 0 && dotPos + 1 < filePathString.length()) {
String extension = filePathString.substring(dotPos + 1);
String extension = ScriptHelpers.getPathExtension(filePath);
if (extension != null) {
return extensionToHandlerMap.get(extension);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.cyclops.integratedscripting.core.network;

import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
import org.cyclops.integratedscripting.api.network.IScript;
import org.cyclops.integratedscripting.api.network.IScriptMember;
import org.cyclops.integratedscripting.evaluate.translation.ValueTranslators;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.jetbrains.annotations.Nullable;

/**
* A script referencing a Graal value.
* @author rubensworks
*/
public class GraalScript implements IScript, IScriptMember {

private final Context graalContext;
private final Value graalValue;

public GraalScript(Context graalContext, Value graalValue) {
this.graalContext = graalContext;
this.graalValue = graalValue;
}

@Nullable
@Override
public IScriptMember getMember(String memberName) {
Value member = this.graalValue.getMember(memberName);
return member == null ? null : new GraalScript(this.graalContext, member);
}

@Override
public IValue getValue() throws EvaluationException {
return ValueTranslators.REGISTRY.translateFromGraal(this.graalContext, graalValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.cyclops.integratedscripting.core.network;

import net.minecraft.network.chat.Component;
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
import org.cyclops.integratedscripting.api.network.IScript;
import org.cyclops.integratedscripting.api.network.IScriptFactory;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.nio.file.Path;

/**
* Instantiates scripts using the GraalVM.
* @author rubensworks
*/
public class GraalScriptFactory implements IScriptFactory {

private final Context graalContext;
private final Value languageBinding;
private final String languageId;

public GraalScriptFactory(Context graalContext, Value languageBinding, String languageId) {
this.graalContext = graalContext;
this.languageBinding = languageBinding;
this.languageId = languageId;
}

@Nullable
@Override
public IScript getScript(int disk, Path path) throws EvaluationException {
try {
Source source = Source.newBuilder(this.languageId, ScriptingNetworkHelpers.getScriptingData().getScripts(disk).get(path), path.toString()).build();
this.graalContext.eval(source);
return new GraalScript(this.graalContext, this.languageBinding);
} catch (IOException e) {
throw new EvaluationException(Component.literal(e.getMessage()));
}
}
}
Loading

0 comments on commit f1fd9e5

Please sign in to comment.