mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-19 06:40:12 +00:00
Add support for Paralithic let expressions
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise;
|
||||
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -88,6 +89,8 @@ public class NoiseAddon implements AddonInitializer {
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> {
|
||||
ParseOptions expressionParseOptions = event.getPack().getExpressionParseOptions();
|
||||
|
||||
CheckedRegistry<Supplier<ObjectTemplate<NoiseSampler>>> noiseRegistry = event.getPack().getOrCreateRegistry(
|
||||
NOISE_SAMPLER_TOKEN);
|
||||
event.getPack()
|
||||
@@ -98,7 +101,7 @@ public class NoiseAddon implements AddonInitializer {
|
||||
.applyLoader(DistanceSampler.DistanceFunction.class,
|
||||
(type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o))
|
||||
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
|
||||
.applyLoader(FunctionTemplate.class, FunctionTemplate::new)
|
||||
.applyLoader(FunctionTemplate.class, () -> new FunctionTemplate(expressionParseOptions))
|
||||
.applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new)
|
||||
.applyLoader(DerivativeNoiseSampler.class, DerivativeNoiseSamplerTemplate::new);
|
||||
|
||||
@@ -156,9 +159,9 @@ public class NoiseAddon implements AddonInitializer {
|
||||
|
||||
Map<String, DimensionApplicableNoiseSampler> packSamplers = new LinkedHashMap<>();
|
||||
Map<String, FunctionTemplate> packFunctions = new LinkedHashMap<>();
|
||||
noiseRegistry.register(addon.key("EXPRESSION"), () -> new ExpressionFunctionTemplate(packSamplers, packFunctions));
|
||||
noiseRegistry.register(addon.key("EXPRESSION"), () -> new ExpressionFunctionTemplate(packSamplers, packFunctions, expressionParseOptions));
|
||||
noiseRegistry.register(addon.key("EXPRESSION_NORMALIZER"),
|
||||
() -> new ExpressionNormalizerTemplate(packSamplers, packFunctions));
|
||||
() -> new ExpressionNormalizerTemplate(packSamplers, packFunctions, expressionParseOptions));
|
||||
|
||||
NoiseConfigPackTemplate template = event.loadTemplate(new NoiseConfigPackTemplate());
|
||||
packSamplers.putAll(template.getSamplers());
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise.config.templates;
|
||||
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
@@ -20,6 +21,8 @@ import com.dfsek.terra.api.config.meta.Meta;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class FunctionTemplate implements ObjectTemplate<FunctionTemplate> {
|
||||
private final ParseOptions parseOptions;
|
||||
|
||||
@Value("arguments")
|
||||
private List<String> args;
|
||||
|
||||
@@ -30,6 +33,10 @@ public class FunctionTemplate implements ObjectTemplate<FunctionTemplate> {
|
||||
@Default
|
||||
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> functions = new LinkedHashMap<>();
|
||||
|
||||
public FunctionTemplate(ParseOptions parseOptions) {
|
||||
this.parseOptions = parseOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionTemplate get() {
|
||||
return this;
|
||||
@@ -47,6 +54,10 @@ public class FunctionTemplate implements ObjectTemplate<FunctionTemplate> {
|
||||
return functions;
|
||||
}
|
||||
|
||||
public ParseOptions getParseOptions() {
|
||||
return parseOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(this == o) return true;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise.config.templates.noise;
|
||||
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
@@ -29,6 +30,7 @@ import static com.dfsek.terra.addons.noise.paralithic.FunctionUtil.convertFuncti
|
||||
public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFunction> {
|
||||
private final Map<String, DimensionApplicableNoiseSampler> globalSamplers;
|
||||
private final Map<String, FunctionTemplate> globalFunctions;
|
||||
private final ParseOptions parseOptions;
|
||||
@Value("variables")
|
||||
@Default
|
||||
private @Meta Map<String, @Meta Double> vars = new HashMap<>();
|
||||
@@ -42,9 +44,11 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
|
||||
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> functions = new LinkedHashMap<>();
|
||||
|
||||
public ExpressionFunctionTemplate(Map<String, DimensionApplicableNoiseSampler> globalSamplers,
|
||||
Map<String, FunctionTemplate> globalFunctions) {
|
||||
Map<String, FunctionTemplate> globalFunctions,
|
||||
ParseOptions parseOptions) {
|
||||
this.globalSamplers = globalSamplers;
|
||||
this.globalFunctions = globalFunctions;
|
||||
this.parseOptions = parseOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +58,7 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
|
||||
var mergedSamplers = new HashMap<>(globalSamplers);
|
||||
mergedSamplers.putAll(samplers);
|
||||
try {
|
||||
return new ExpressionFunction(convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars);
|
||||
return new ExpressionFunction(convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars, parseOptions);
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to parse expression.", e);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.dfsek.terra.addons.noise.config.templates.normalizer;
|
||||
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
@@ -29,6 +30,7 @@ public class ExpressionNormalizerTemplate extends NormalizerTemplate<ExpressionN
|
||||
|
||||
private final Map<String, DimensionApplicableNoiseSampler> globalSamplers;
|
||||
private final Map<String, FunctionTemplate> globalFunctions;
|
||||
private final ParseOptions parseOptions;
|
||||
|
||||
@Value("expression")
|
||||
private @Meta String expression;
|
||||
@@ -46,9 +48,11 @@ public class ExpressionNormalizerTemplate extends NormalizerTemplate<ExpressionN
|
||||
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> functions = new LinkedHashMap<>();
|
||||
|
||||
public ExpressionNormalizerTemplate(Map<String, DimensionApplicableNoiseSampler> globalSamplers,
|
||||
Map<String, FunctionTemplate> globalFunctions) {
|
||||
Map<String, FunctionTemplate> globalFunctions,
|
||||
ParseOptions parseOptions) {
|
||||
this.globalSamplers = globalSamplers;
|
||||
this.globalFunctions = globalFunctions;
|
||||
this.parseOptions = parseOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +62,7 @@ public class ExpressionNormalizerTemplate extends NormalizerTemplate<ExpressionN
|
||||
var mergedSamplers = new HashMap<>(globalSamplers);
|
||||
mergedSamplers.putAll(samplers);
|
||||
try {
|
||||
return new ExpressionNormalizer(function, convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars);
|
||||
return new ExpressionNormalizer(function, convertFunctionsAndSamplers(mergedFunctions, mergedSamplers), expression, vars, parseOptions);
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to parse expression.", e);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ package com.dfsek.terra.addons.noise.normalizer;
|
||||
|
||||
import com.dfsek.paralithic.Expression;
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
@@ -15,12 +17,24 @@ public class ExpressionNormalizer extends Normalizer {
|
||||
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionNormalizer(NoiseSampler sampler, Map<String, Function> functions, String eq, Map<String, Double> vars)
|
||||
public ExpressionNormalizer(NoiseSampler sampler, Map<String, Function> functions, String eq, Map<String, Double> vars, ParseOptions parseOptions)
|
||||
throws ParseException {
|
||||
super(sampler);
|
||||
Parser p = new Parser();
|
||||
|
||||
Parser p = new Parser(parseOptions);
|
||||
Scope scope = new Scope();
|
||||
scope.addInvocationVariable("in");
|
||||
|
||||
// 'in' was used as the invocation variable but conflicts with
|
||||
// the new 'in' keyword in Paralithic used to denote the end of a let
|
||||
// expression. To maintain backwards compatibility but also enable the use
|
||||
// of let expressions, if they're enabled then use the longer 'input'
|
||||
// invocation variable instead.
|
||||
if (parseOptions.useLetExpressions()) {
|
||||
scope.addInvocationVariable("input");
|
||||
} else {
|
||||
scope.addInvocationVariable("in");
|
||||
}
|
||||
|
||||
vars.forEach(scope::create);
|
||||
functions.forEach(p::registerFunction);
|
||||
expression = p.parse(eq, scope);
|
||||
|
||||
@@ -35,7 +35,7 @@ public class UserDefinedFunction implements DynamicFunction {
|
||||
public static UserDefinedFunction newInstance(FunctionTemplate template) throws ParseException {
|
||||
UserDefinedFunction function = CACHE.get(template);
|
||||
if(function == null) {
|
||||
Parser parser = new Parser();
|
||||
Parser parser = new Parser(template.getParseOptions());
|
||||
Scope parent = new Scope();
|
||||
|
||||
Scope functionScope = new Scope().withParent(parent);
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.dfsek.terra.addons.noise.samplers.noise;
|
||||
|
||||
import com.dfsek.paralithic.Expression;
|
||||
import com.dfsek.paralithic.eval.parser.Parser;
|
||||
import com.dfsek.paralithic.eval.parser.Parser.ParseOptions;
|
||||
import com.dfsek.paralithic.eval.parser.Scope;
|
||||
import com.dfsek.paralithic.eval.tokenizer.ParseException;
|
||||
import com.dfsek.paralithic.functions.Function;
|
||||
@@ -24,8 +25,8 @@ import com.dfsek.terra.addons.noise.paralithic.noise.SeedContext;
|
||||
public class ExpressionFunction extends NoiseFunction {
|
||||
private final Expression expression;
|
||||
|
||||
public ExpressionFunction(Map<String, Function> functions, String eq, Map<String, Double> vars) throws ParseException {
|
||||
Parser p = new Parser();
|
||||
public ExpressionFunction(Map<String, Function> functions, String eq, Map<String, Double> vars, ParseOptions parseOptions) throws ParseException {
|
||||
Parser p = new Parser(parseOptions);
|
||||
Scope scope = new Scope();
|
||||
|
||||
scope.addInvocationVariable("x");
|
||||
|
||||
Reference in New Issue
Block a user