Skip to content

Commit ab92ab8

Browse files
committed
Reduce assign() runtime actions
- Do not redefine variables in variable list when not necessary. - Unwrap IVariable values only once. - Directly create new IVariable with correct values when necessary.
1 parent d4bc1ef commit ab92ab8

File tree

1 file changed

+67
-26
lines changed

1 file changed

+67
-26
lines changed

src/main/java/com/laytonsmith/core/functions/DataHandling.java

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -342,51 +342,92 @@ public Integer[] numArgs() {
342342
@Override
343343
public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommandException, ConfigRuntimeException {
344344
IVariableList list = env.getEnv(GlobalEnv.class).GetVarList();
345-
int offset;
346-
CClassType type;
347-
String name;
345+
IVariable var;
348346
if(args.length == 3) {
349-
offset = 1;
350-
if(!(args[offset] instanceof IVariable)) {
347+
348+
// Get and validate variable name.
349+
if(!(args[1] instanceof IVariable)) {
351350
throw new CRECastException(getName() + " with 3 arguments only accepts an ivariable as the second argument.", t);
352351
}
353-
name = ((IVariable) args[offset]).getVariableName();
354-
if(list.has(name) && env.getEnv(GlobalEnv.class).GetFlag("no-check-duplicate-assign") == null) {
352+
String varName = ((IVariable) args[1]).getVariableName();
353+
if(list.has(varName) && env.getEnv(GlobalEnv.class).GetFlag("no-check-duplicate-assign") == null) {
355354
if(env.getEnv(GlobalEnv.class).GetFlag("closure-warn-overwrite") != null) {
356355
MSLog.GetLogger().Log(MSLog.Tags.RUNTIME, LogLevel.WARNING,
357-
"The variable " + name + " is hiding another value of the"
356+
"The variable " + varName + " is hiding another value of the"
358357
+ " same name in the main scope.", t);
359-
} else if(!StaticAnalysis.enabled() && t != list.get(name, t, true, env).getDefinedTarget()) {
360-
MSLog.GetLogger().Log(MSLog.Tags.RUNTIME, LogLevel.ERROR, name + " was already defined at "
361-
+ list.get(name, t, true, env).getDefinedTarget() + " but is being redefined.", t);
358+
} else if(!StaticAnalysis.enabled() && t != list.get(varName, t, true, env).getDefinedTarget()) {
359+
MSLog.GetLogger().Log(MSLog.Tags.RUNTIME, LogLevel.ERROR, varName + " was already defined at "
360+
+ list.get(varName, t, true, env).getDefinedTarget() + " but is being redefined.", t);
362361
}
363362
}
364-
type = ArgumentValidation.getClassType(args[0], t);
363+
364+
// Get and validate variable type.
365+
CClassType type = ArgumentValidation.getClassType(args[0], t);
365366
Boolean varArgsAllowed = env.getEnv(GlobalEnv.class).GetFlag("var-args-allowed");
366367
if(varArgsAllowed == null) {
367368
varArgsAllowed = false;
368369
}
369370
if(type.isVarargs() && !varArgsAllowed) {
370371
throw new CRECastException("Cannot use varargs type in this context", t);
371372
}
373+
if(type.equals(CVoid.TYPE)) {
374+
throw new CRECastException("Variables may not be of type void", t);
375+
}
376+
377+
// Get assigned value.
378+
Mixed val = args[2];
379+
380+
// Unwrap assigned value from IVariable if an IVariable is passed.
381+
if(val instanceof IVariable ivar) {
382+
val = list.get(ivar.getVariableName(), ivar.getTarget(), env).ival();
383+
}
384+
385+
// Validate assigned value.
386+
if(val instanceof CVoid) {
387+
throw new CRECastException("Void may not be assigned to a variable", t);
388+
}
389+
if(!InstanceofUtil.isInstanceof(val.typeof(), type, env)) {
390+
throw new CRECastException(varName + " is of type " + type.val() + ", but a value of type "
391+
+ val.typeof() + " was assigned to it.", t);
392+
}
393+
394+
// Set variable in variable list.
395+
var = new IVariable(type, varName, val, t);
396+
list.set(var);
397+
372398
} else {
373-
offset = 0;
374-
if(!(args[offset] instanceof IVariable)) {
399+
400+
// Get and validate variable name.
401+
if(!(args[0] instanceof IVariable)) {
375402
throw new CRECastException(getName() + " with 2 arguments only accepts an ivariable as the first argument.", t);
376403
}
377-
name = ((IVariable) args[offset]).getVariableName();
378-
IVariable listVar = list.get(name, t, true, env);
379-
t = listVar.getDefinedTarget();
380-
type = listVar.getDefinedType();
381-
}
382-
Mixed c = args[offset + 1];
383-
while(c instanceof IVariable) {
384-
IVariable cur = (IVariable) c;
385-
c = list.get(cur.getVariableName(), cur.getTarget(), env).ival();
404+
String varName = ((IVariable) args[0]).getVariableName();
405+
406+
// Get assigned value.
407+
Mixed val = args[1];
408+
409+
// Unwrap assigned value from IVariable if an IVariable is passed.
410+
if(val instanceof IVariable ivar) {
411+
val = list.get(ivar.getVariableName(), ivar.getTarget(), env).ival();
412+
}
413+
414+
// Validate assigned value and set variable in variable list.
415+
if(val instanceof CVoid) {
416+
throw new CRECastException("Void may not be assigned to a variable", t);
417+
}
418+
var = list.get(varName);
419+
if(var == null) {
420+
var = new IVariable(Auto.TYPE, varName, val, t);
421+
list.set(var);
422+
} else {
423+
if(!InstanceofUtil.isInstanceof(val.typeof(), var.getDefinedType(), env)) {
424+
throw new CRECastException(varName + " is of type " + var.getDefinedType()
425+
+ ", but a value of type " + val.typeof() + " was assigned to it.", t);
426+
}
427+
var.setIval(val);
428+
}
386429
}
387-
IVariable v = new IVariable(type, name, c, t, env);
388-
list.set(v);
389-
return v;
430+
return var;
390431
}
391432

392433
@Override

0 commit comments

Comments
 (0)