use of org.projectnessie.cel.parser.Macro in project cel-java by projectnessie.
the class CELTest method CustomMacro.
@Test
void CustomMacro() {
Macro joinMacro = newReceiverMacro("join", 1, (eh, target, args) -> {
Expr delim = args.get(0);
Expr iterIdent = eh.ident("__iter__");
Expr accuIdent = eh.ident("__result__");
Expr init = eh.literalString("");
Expr condition = eh.literalBool(true);
Expr step = eh.globalCall(Operator.Conditional.id, eh.globalCall(Operator.Greater.id, eh.receiverCall("size", accuIdent, emptyList()), eh.literalInt(0)), eh.globalCall(Operator.Add.id, eh.globalCall(Operator.Add.id, accuIdent, delim), iterIdent), iterIdent);
return eh.fold("__iter__", target, "__result__", init, condition, step, accuIdent);
});
Env e = newEnv(macros(joinMacro));
AstIssuesTuple astIss = e.compile("['hello', 'cel', 'friend'].join(',')");
assertThat(astIss.hasIssues()).isFalse();
Program prg = e.program(astIss.getAst(), evalOptions(OptExhaustiveEval));
EvalResult out = prg.eval(noVars());
assertThat(out.getVal().equal(stringOf("hello,cel,friend"))).isSameAs(True);
}
use of org.projectnessie.cel.parser.Macro in project cel-java by projectnessie.
the class CheckerEnv method addOverload.
/**
* addOverload adds overload to function declaration f. Returns one or more errorMsg values if the
* overload overlaps with an existing overload or macro.
*/
Decl addOverload(Decl f, Overload overload, List<String> errMsgs) {
FunctionDecl function = f.getFunction();
Mapping emptyMappings = newMapping();
Type overloadFunction = Decls.newFunctionType(overload.getResultType(), overload.getParamsList());
Type overloadErased = substitute(emptyMappings, overloadFunction, true);
boolean hasErr = false;
for (Overload existing : function.getOverloadsList()) {
Type existingFunction = Decls.newFunctionType(existing.getResultType(), existing.getParamsList());
Type existingErased = substitute(emptyMappings, existingFunction, true);
boolean overlap = isAssignable(emptyMappings, overloadErased, existingErased) != null || isAssignable(emptyMappings, existingErased, overloadErased) != null;
if (overlap && overload.getIsInstanceFunction() == existing.getIsInstanceFunction()) {
errMsgs.add(overlappingOverloadError(f.getName(), overload.getOverloadId(), overloadFunction, existing.getOverloadId(), existingFunction));
hasErr = true;
}
}
for (Macro macro : Macro.AllMacros) {
if (macro.function().equals(f.getName()) && macro.isReceiverStyle() == overload.getIsInstanceFunction() && macro.argCount() == overload.getParamsCount()) {
errMsgs.add(overlappingMacroError(f.getName(), macro.argCount()));
hasErr = true;
}
}
if (hasErr) {
return f;
}
function = function.toBuilder().addOverloads(overload).build();
f = f.toBuilder().setFunction(function).build();
return f;
}
use of org.projectnessie.cel.parser.Macro in project cel-java by projectnessie.
the class Env method extend.
/**
* Extend the current environment with additional options to produce a new Env.
*
* <p>Note, the extended Env value should not share memory with the original. It is possible,
* however, that a CustomTypeAdapter or CustomTypeProvider options could provide values which are
* mutable. To ensure separation of state between extended environments either make sure the
* TypeAdapter and TypeProvider are immutable, or that their underlying implementations are based
* on the ref.TypeRegistry which provides a Copy method which will be invoked by this method.
*/
public Env extend(List<EnvOption> opts) {
if (chkErr != null) {
throw chkErr;
}
// Copy slices.
List<Decl> decsCopy = new ArrayList<>(declarations);
List<Macro> macsCopy = new ArrayList<>(macros);
List<ProgramOption> progOptsCopy = new ArrayList<>(progOpts);
// Copy the adapter / provider if they appear to be mutable.
TypeAdapter adapter = this.adapter;
TypeProvider provider = this.provider;
// TypeRegistry as the base implementation are captured below.
if (this.adapter instanceof TypeRegistry && this.provider instanceof TypeRegistry) {
TypeRegistry adapterReg = (TypeRegistry) this.adapter;
TypeRegistry providerReg = (TypeRegistry) this.provider;
TypeRegistry reg = providerReg.copy();
provider = reg;
// to the same ref.TypeRegistry as the provider.
if (adapterReg.equals(providerReg)) {
adapter = reg;
} else {
// Otherwise, make a copy of the adapter.
adapter = adapterReg.copy();
}
} else if (this.provider instanceof TypeRegistry) {
provider = ((TypeRegistry) this.provider).copy();
} else if (this.adapter instanceof TypeRegistry) {
adapter = ((TypeRegistry) this.adapter).copy();
}
Set<EnvFeature> featuresCopy = EnumSet.copyOf(this.features);
Env ext = new Env(this.container, decsCopy, macsCopy, adapter, provider, featuresCopy, progOptsCopy);
return ext.configure(opts);
}
Aggregations