@@ -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