WIP unpacking of parameters.

This commit is contained in:
gnembon committed 2021-04-21 12:21:47 -03:00
1 parent 72a3d74a97
commit a65d16c9ba
11 files changed
+105 -29

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ public class Context
public static final int LOCALIZATION = 8;
public static final int LVALUE = 9;
public static final int MAPDEF = 10;
public static final int CALLARGS = 11;
public Map<String, LazyValue> variables = new HashMap<>();
+10 -6
View File
@@ -773,12 +773,16 @@ public class Expression
stack.set(stack.size() - 1, stack.peek() - 2 + 1);
break;
case FUNCTION:
ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions
int numParams = stack.pop();
if (f != null && !f.numParamsVaries() && numParams != f.getNumParams())
{
throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams);
}
//ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions
//int numParams = stack.pop();
//if (f != null && !f.numParamsVaries() && numParams != f.getNumParams())
//{
// throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams);
//}
stack.pop();
// due to unpacking, all functions can have variable number of arguments
// we will be checking that at runtime.
// TODO try analyze arguments and assess if its possible that they are static
if (stack.size() <= 0)
{
throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded");
+30 -4
View File
@@ -1,6 +1,9 @@
package carpet.script;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.value.FunctionUnpackedArgumentsValue;
import carpet.script.value.ListValue;
import carpet.script.value.Value;
import java.util.ArrayList;
@@ -85,6 +88,30 @@ public abstract class Fluff
super(numParams);
}
public static List<Value> unpackArgs(List<LazyValue> lzargs, Context c)
{
List<Value> args = new ArrayList<>();
for (LazyValue lv : lzargs)
{
Value arg = lv.evalValue(c, Context.CALLARGS);
if (arg instanceof FunctionUnpackedArgumentsValue)
{
args.addAll(((ListValue) arg).getItems());
}
else
{
args.add(arg);
}
}
return args;
}
public void checkArgs(int candidates)
{
if (!numParamsVaries() && getNumParams() !=candidates)
throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + candidates);
}
@Override
public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List<LazyValue> lazyParams)
{
@@ -100,10 +127,9 @@ public abstract class Fluff
private List<Value> getParams(Context c) {
if (params == null) {
params = new ArrayList<>();
for (LazyValue lazyParam : lazyParams) {
params.add(lazyParam.evalValue(c)); // none type default by design
}
// very likely needs to be dynamic, so not static like here, or remember if it was.
params = unpackArgs(lazyParams, c);
checkArgs(params.size());
}
return params;
}
@@ -834,12 +834,13 @@ public class Auxiliary {
throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name");
long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong();
FunctionArgument<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true);
FunctionArgument<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false);
List<Value> args = functionArgument.unpackArgs(c);
CarpetServer.scriptServer.events.scheduleCall(
(CarpetContext) c,
functionArgument.function,
FunctionValue.resolveArgs(functionArgument.args, c, t),
args,
delay
);
return (c_, t_) -> Value.TRUE;
@@ -1043,7 +1044,7 @@ public class Auxiliary {
}
else
{
success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, FunctionValue.resolveArgs(callback.args, c, t) )?Value.TRUE:Value.FALSE;
success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.unpackArgs(c) )?Value.TRUE:Value.FALSE;
}
return (cc, tt) -> success;
});
@@ -308,7 +308,7 @@ public class Entities {
}
else
{
types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t)));
types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.unpackArgs(c)));
}
Value ret = new NumericValue(types.size());
return (cc, tt) -> ret;
@@ -326,7 +326,7 @@ public class Entities {
FunctionArgument<LazyValue> funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false);
((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t));
((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.unpackArgs(c));
return LazyValue.NULL;
});
@@ -1,6 +1,7 @@
package carpet.script.argument;
import carpet.script.Context;
import carpet.script.Fluff;
import carpet.script.LazyValue;
import carpet.script.ScriptHost;
import carpet.script.bundled.Module;
@@ -94,4 +95,14 @@ public class FunctionArgument<T> extends Argument
return new FunctionArgument<>(function, 0, args);
}
public void checkArgs() {
function.checkArgs(args.size());
}
public List<Value> unpackArgs(Context c) {
List<Value> unpackedArgs = Fluff.AbstractFunction.unpackArgs((List<LazyValue>) args, c);
function.checkArgs(unpackedArgs.size());
return unpackedArgs;
}
}
@@ -6,12 +6,14 @@ import carpet.script.LazyValue;
import carpet.script.argument.FunctionArgument;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ReturnStatement;
import carpet.script.value.AbstractListValue;
import carpet.script.value.FunctionSignatureValue;
import carpet.script.value.FunctionValue;
import carpet.script.value.FunctionAnnotationValue;
import carpet.script.value.ListValue;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
@@ -90,9 +92,20 @@ public class Functions {
expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) ->
{
if (t != Context.LOCALIZATION)
throw new InternalExpressionException("That functionality has not been implemented yet.");
if (t == Context.LOCALIZATION)
return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1);
if (t == Context.CALLARGS)
{
Value params = lv.evalValue(c, Context.NONE);
if (params instanceof ListValue)
return (cc, tt) -> params;
if (!(params instanceof AbstractListValue))
throw new InternalExpressionException("Unable to unpack a non-list");
Value unpacked = ListValue.wrap(ImmutableList.copyOf(((AbstractListValue) params).iterator()));
return (cc, tt) -> unpacked;
}
throw new InternalExpressionException("That functionality has not been implemented yet.");
});
//assigns const procedure to the lhs, returning its previous value
@@ -19,7 +19,7 @@ public class Threading
if (lv.size() == 0)
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
FunctionArgument<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true);
ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t));
ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c));
Thread.yield();
return (cc, tt) -> thread;
});
@@ -30,7 +30,7 @@ public class Threading
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
Value queue = lv.get(0).evalValue(c);
FunctionArgument<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true);
ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t));
ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c));
Thread.yield();
return (cc, tt) -> thread;
});
@@ -0,0 +1,10 @@
package carpet.script.value;
import java.util.List;
public class FunctionUnpackedArgumentsValue extends ListValue
{
public FunctionUnpackedArgumentsValue(List<Value> list) {
super(list);
}
}
@@ -11,7 +11,6 @@ import carpet.script.exception.ContinueStatement;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ReturnStatement;
import carpet.script.exception.ThrowStatement;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -173,15 +172,26 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
}
@Override
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
public void checkArgs(int candidates)
{
assertArgsOk(lazyParams, (fixedArgs) ->{
int actual = getArguments().size();
if (candidates < actual)
throw new InternalExpressionException("Function " + getPrettyString() + " requires at least " + actual + " arguments");
if (candidates > actual && getVarArgs() == null)
throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments");
}
@Override
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyPrams)
{
List<Value> resolvedArgs = Fluff.AbstractFunction.unpackArgs(lazyPrams, c);
assertArgsOk(resolvedArgs, (fixedArgs) ->{
if (fixedArgs) // wrong number of args for fixed args
{
throw new ExpressionException(c, e, t,
"Incorrect number of arguments for function "+name+
". Should be "+args.size()+", not "+lazyParams.size()+" like "+args
". Should be "+args.size()+", not "+resolvedArgs.size()+" like "+args
);
}
else // too few args for varargs
@@ -190,7 +200,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
argList.add("... "+varArgs);
throw new ExpressionException(c, e, t,
"Incorrect number of arguments for function "+name+
". Should be at least "+args.size()+", not "+lazyParams.size()+" like "+argList
". Should be at least "+args.size()+", not "+resolvedArgs.size()+" like "+argList
);
}
});
@@ -200,15 +210,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
for (int i=0; i<args.size(); i++)
{
String arg = args.get(i);
Value val = lazyParams.get(i).evalValue(c).reboundedTo(arg); // todo check if we need to copy that
Value val = resolvedArgs.get(i).reboundedTo(arg); // todo check if we need to copy that
newFrame.setVariable(arg, (cc, tt) -> val);
}
if (varArgs != null)
{
List<Value> extraParams = new ArrayList<>();
for (int i = args.size(), mx = lazyParams.size(); i < mx; i++)
for (int i = args.size(), mx = resolvedArgs.size(); i < mx; i++)
{
extraParams.add(lazyParams.get(i).evalValue(c).reboundedTo(null)); // copy by value I guess
extraParams.add(resolvedArgs.get(i).reboundedTo(null)); // copy by value I guess
}
Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that?
newFrame.setVariable(varArgs, (cc, tt) -> rest);
@@ -70,7 +70,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
items.addAll(list);
}
private ListValue(List<Value> list)
protected ListValue(List<Value> list)
{
items = list;
}