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
+106 -30

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 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<>();
+10 -6
View File
@@ -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");
+30 -4
View File
@@ -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;
} }