WIP unpacking of parameters.
This commit is contained in:
1 parent
72a3d74a97
commit
a65d16c9ba
11 files changed
+106
-30
No files matched your search
@@ -19,6 +19,7 @@ public class Context
|
|||||||
public static final int LOCALIZATION = 8;
|
public static final int LOCALIZATION = 8;
|
||||||
public static final int LVALUE = 9;
|
public static final int LVALUE = 9;
|
||||||
public static final int MAPDEF = 10;
|
public static final int MAPDEF = 10;
|
||||||
|
public static final int CALLARGS = 11;
|
||||||
|
|
||||||
public Map<String, LazyValue> variables = new HashMap<>();
|
public Map<String, LazyValue> variables = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -773,12 +773,16 @@ public class Expression
|
|||||||
stack.set(stack.size() - 1, stack.peek() - 2 + 1);
|
stack.set(stack.size() - 1, stack.peek() - 2 + 1);
|
||||||
break;
|
break;
|
||||||
case FUNCTION:
|
case FUNCTION:
|
||||||
ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions
|
//ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions
|
||||||
int numParams = stack.pop();
|
//int numParams = stack.pop();
|
||||||
if (f != null && !f.numParamsVaries() && numParams != f.getNumParams())
|
//if (f != null && !f.numParamsVaries() && numParams != f.getNumParams())
|
||||||
{
|
//{
|
||||||
throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams);
|
// 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)
|
if (stack.size() <= 0)
|
||||||
{
|
{
|
||||||
throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded");
|
throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded");
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package carpet.script;
|
package carpet.script;
|
||||||
|
|
||||||
import carpet.script.exception.ExpressionException;
|
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 carpet.script.value.Value;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -85,6 +88,30 @@ public abstract class Fluff
|
|||||||
super(numParams);
|
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
|
@Override
|
||||||
public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List<LazyValue> lazyParams)
|
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) {
|
private List<Value> getParams(Context c) {
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
params = new ArrayList<>();
|
// very likely needs to be dynamic, so not static like here, or remember if it was.
|
||||||
for (LazyValue lazyParam : lazyParams) {
|
params = unpackArgs(lazyParams, c);
|
||||||
params.add(lazyParam.evalValue(c)); // none type default by design
|
checkArgs(params.size());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -834,12 +834,13 @@ public class Auxiliary {
|
|||||||
throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name");
|
throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name");
|
||||||
long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong();
|
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(
|
CarpetServer.scriptServer.events.scheduleCall(
|
||||||
(CarpetContext) c,
|
(CarpetContext) c,
|
||||||
functionArgument.function,
|
functionArgument.function,
|
||||||
FunctionValue.resolveArgs(functionArgument.args, c, t),
|
args,
|
||||||
delay
|
delay
|
||||||
);
|
);
|
||||||
return (c_, t_) -> Value.TRUE;
|
return (c_, t_) -> Value.TRUE;
|
||||||
@@ -1043,7 +1044,7 @@ public class Auxiliary {
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return (cc, tt) -> success;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ public class Entities {
|
|||||||
}
|
}
|
||||||
else
|
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());
|
Value ret = new NumericValue(types.size());
|
||||||
return (cc, tt) -> ret;
|
return (cc, tt) -> ret;
|
||||||
@@ -326,7 +326,7 @@ public class Entities {
|
|||||||
|
|
||||||
FunctionArgument<LazyValue> funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false);
|
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;
|
return LazyValue.NULL;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package carpet.script.argument;
|
package carpet.script.argument;
|
||||||
|
|
||||||
import carpet.script.Context;
|
import carpet.script.Context;
|
||||||
|
import carpet.script.Fluff;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.ScriptHost;
|
import carpet.script.ScriptHost;
|
||||||
import carpet.script.bundled.Module;
|
import carpet.script.bundled.Module;
|
||||||
@@ -94,4 +95,14 @@ public class FunctionArgument<T> extends Argument
|
|||||||
|
|
||||||
return new FunctionArgument<>(function, 0, args);
|
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.argument.FunctionArgument;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.exception.ReturnStatement;
|
import carpet.script.exception.ReturnStatement;
|
||||||
|
import carpet.script.value.AbstractListValue;
|
||||||
import carpet.script.value.FunctionSignatureValue;
|
import carpet.script.value.FunctionSignatureValue;
|
||||||
import carpet.script.value.FunctionValue;
|
import carpet.script.value.FunctionValue;
|
||||||
import carpet.script.value.FunctionAnnotationValue;
|
import carpet.script.value.FunctionAnnotationValue;
|
||||||
import carpet.script.value.ListValue;
|
import carpet.script.value.ListValue;
|
||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -90,9 +92,20 @@ public class Functions {
|
|||||||
|
|
||||||
expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) ->
|
expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (t != Context.LOCALIZATION)
|
if (t == Context.LOCALIZATION)
|
||||||
throw new InternalExpressionException("That functionality has not been implemented yet.");
|
return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1);
|
||||||
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
|
//assigns const procedure to the lhs, returning its previous value
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class Threading
|
|||||||
if (lv.size() == 0)
|
if (lv.size() == 0)
|
||||||
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
|
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);
|
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();
|
Thread.yield();
|
||||||
return (cc, tt) -> thread;
|
return (cc, tt) -> thread;
|
||||||
});
|
});
|
||||||
@@ -30,7 +30,7 @@ public class Threading
|
|||||||
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
|
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
|
||||||
Value queue = lv.get(0).evalValue(c);
|
Value queue = lv.get(0).evalValue(c);
|
||||||
FunctionArgument<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true);
|
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();
|
Thread.yield();
|
||||||
return (cc, tt) -> thread;
|
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.ExpressionException;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.exception.ReturnStatement;
|
import carpet.script.exception.ReturnStatement;
|
||||||
import carpet.script.exception.ThrowStatement;
|
|
||||||
import net.minecraft.nbt.StringTag;
|
import net.minecraft.nbt.StringTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
@@ -173,15 +172,26 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void checkArgs(int candidates)
|
||||||
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
|
||||||
{
|
{
|
||||||
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
|
if (fixedArgs) // wrong number of args for fixed args
|
||||||
{
|
{
|
||||||
throw new ExpressionException(c, e, t,
|
throw new ExpressionException(c, e, t,
|
||||||
"Incorrect number of arguments for function "+name+
|
"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
|
else // too few args for varargs
|
||||||
@@ -190,7 +200,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
|||||||
argList.add("... "+varArgs);
|
argList.add("... "+varArgs);
|
||||||
throw new ExpressionException(c, e, t,
|
throw new ExpressionException(c, e, t,
|
||||||
"Incorrect number of arguments for function "+name+
|
"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++)
|
for (int i=0; i<args.size(); i++)
|
||||||
{
|
{
|
||||||
String arg = args.get(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);
|
newFrame.setVariable(arg, (cc, tt) -> val);
|
||||||
}
|
}
|
||||||
if (varArgs != null)
|
if (varArgs != null)
|
||||||
{
|
{
|
||||||
List<Value> extraParams = new ArrayList<>();
|
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?
|
Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that?
|
||||||
newFrame.setVariable(varArgs, (cc, tt) -> rest);
|
newFrame.setVariable(varArgs, (cc, tt) -> rest);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
items.addAll(list);
|
items.addAll(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListValue(List<Value> list)
|
protected ListValue(List<Value> list)
|
||||||
{
|
{
|
||||||
items = list;
|
items = list;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user