11package me .anatoliy57 .chunit .functions ;
22
33import com .laytonsmith .annotations .api ;
4+ import com .laytonsmith .core .ArgumentValidation ;
45import com .laytonsmith .core .Globals ;
56import com .laytonsmith .core .MSVersion ;
67import com .laytonsmith .core .Procedure ;
1314import com .laytonsmith .core .exceptions .CRE .CREThrowable ;
1415import com .laytonsmith .core .exceptions .ConfigRuntimeException ;
1516import com .laytonsmith .core .functions .AbstractFunction ;
17+ import com .laytonsmith .core .functions .ArrayHandling ;
1618import com .laytonsmith .core .natives .interfaces .Mixed ;
19+ import me .anatoliy57 .chunit .core .ProcClosure ;
1720
1821import java .util .*;
1922
2023public class Environments {
2124 public static String docs () {
22- return "A set of functions for environment" ;
25+ return "A set of functions for environment. " ;
2326 }
2427
2528 public static final Map <String , Environment > environmentMap = new HashMap <>();
@@ -39,7 +42,7 @@ public Integer[] numArgs() {
3942 }
4043
4144 public String docs () {
42- return "void {id} Save reference of environment by id" ;
45+ return "void {id} Save reference of environment by id. " ;
4346 }
4447
4548 public Class <? extends CREThrowable >[] thrown () {
@@ -83,7 +86,7 @@ public Integer[] numArgs() {
8386 }
8487
8588 public String docs () {
86- return "void {id} Remove reference of environment by id" ;
89+ return "void {id} Remove reference of environment by id. " ;
8790 }
8891
8992 public Class <? extends CREThrowable >[] thrown () {
@@ -127,7 +130,7 @@ public Integer[] numArgs() {
127130 }
128131
129132 public String docs () {
130- return "void {id, proc, replacement} Swaps one procedure for another (or given closure) in a saved environment" ;
133+ return "void {id, proc, replacement} Swaps one procedure for another (or given closure) in a saved environment. " ;
131134 }
132135
133136 public Class <? extends CREThrowable >[] thrown () {
@@ -156,7 +159,7 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
156159 Map <String , Procedure > procedures = global .GetProcs ();
157160
158161 if (!procedures .containsKey (proc )) {
159- throw new CREInvalidProcedureException ("Unknown procedure \" " + proc + '"' , t );
162+ throw new CREInvalidProcedureException ("Unknown procedure \" " + proc + " \" in saved environment" , t );
160163 }
161164
162165 Procedure val ;
@@ -166,7 +169,7 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
166169 val = new ProcClosure (proc , (CClosure ) replacement , t );
167170 } else {
168171 val = Optional .ofNullable (currentProcedures .get (replacement .val ())).orElseThrow (() -> {
169- throw new CREInvalidProcedureException ("Unknown procedure \" " + replacement .val () + '"' , t );
172+ throw new CREInvalidProcedureException ("Unknown procedure \" " + replacement .val () + " \" in current environment" , t );
170173 });
171174 }
172175
@@ -178,46 +181,128 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
178181 public Boolean runAsync () {
179182 return null ;
180183 }
184+ }
181185
182- private static class ProcClosure extends Procedure implements Cloneable {
186+ @ api
187+ public static class x_add_procedure extends AbstractFunction {
183188
184- private final String name ;
185- private CClosure closure ;
189+ public x_add_procedure () {
190+ }
186191
187- public ProcClosure (String name , CClosure closure , Target t ) {
188- super (name , null , Collections .EMPTY_LIST , null , t );
192+ public String getName () {
193+ return "x_add_procedure" ;
194+ }
189195
190- this .name = name ;
191- this .closure = closure ;
192- }
196+ public Integer [] numArgs () {
197+ return new Integer []{2 , 3 };
198+ }
199+
200+ public String docs () {
201+ return "void {id, procName, [closure]} Add procedure (or given closure as procedure named by procName) in a saved environment." ;
202+ }
203+
204+ public Class <? extends CREThrowable >[] thrown () {
205+ return new Class []{CRECastException .class , CREInvalidProcedureException .class , CREIndexOverflowException .class };
206+ }
207+
208+ public boolean isRestricted () {
209+ return true ;
210+ }
211+
212+ public MSVersion since () {
213+ return MSVersion .V3_0_2 ;
214+ }
193215
194- @ Override
195- public Mixed execute (List <Mixed > args , Environment oldEnv , Target t ) {
196- Mixed [] values = new Mixed [args .size ()];
197- args .toArray (values );
198- return closure .executeCallable (values );
216+ public Mixed exec (Target t , Environment env , Mixed ... args ) throws ConfigRuntimeException {
217+ String id = args [0 ].val ();
218+ String proc = args [1 ].val ();
219+
220+ Environment savedEnv ;
221+ synchronized (environmentMap ) {
222+ savedEnv = Optional .ofNullable (environmentMap .get (id )).orElseThrow (() -> {
223+ throw new CREIndexOverflowException ("No environment with this id \" " +id +"\" found" , t );
224+ });
199225 }
226+ GlobalEnv global = savedEnv .getEnv (GlobalEnv .class );
227+ Map <String , Procedure > procedures = global .GetProcs ();
200228
201- @ Override
202- public Procedure clone () throws CloneNotSupportedException {
203- ProcClosure clone = ( ProcClosure ) super . clone ();
229+ if ( procedures . containsKey ( proc )) {
230+ throw new CREInvalidProcedureException ( "Procedure already exists \" " + proc + " \" in saved environment" , t );
231+ }
204232
205- if (closure != null ) {
206- clone .closure = this .closure .clone ();
233+ Procedure val ;
234+ if (args .length == 3 ) {
235+ if (!args [2 ].isInstanceOf (CClosure .TYPE )) {
236+ throw new CRECastException ("Expecting a closure for argument 2" , t );
207237 }
238+ CClosure closure = (CClosure ) args [2 ];
239+ val = new ProcClosure (proc , closure , t );
240+ } else {
241+ Map <String , Procedure > currentProcedures = env .getEnv (GlobalEnv .class ).GetProcs ();
208242
209- return clone ;
243+ val = Optional .ofNullable (currentProcedures .get (proc )).orElseThrow (() -> {
244+ throw new CREInvalidProcedureException ("Unknown procedure \" " + proc + "\" in current environment" , t );
245+ });
210246 }
211247
212- @ Override
213- public void definitelyNotConstant () {
214- super .definitelyNotConstant ();
215- }
248+ procedures .put (proc , val );
216249
217- @ Override
218- public String getName () {
219- return name ;
250+ return CVoid .VOID ;
251+ }
252+
253+ public Boolean runAsync () {
254+ return null ;
255+ }
256+ }
257+
258+ @ api
259+ public static class x_remove_procedure extends AbstractFunction {
260+
261+ public x_remove_procedure () {
262+ }
263+
264+ public String getName () {
265+ return "x_remove_procedure" ;
266+ }
267+
268+ public Integer [] numArgs () {
269+ return new Integer []{2 };
270+ }
271+
272+ public String docs () {
273+ return "boolean {id, procName} Remove procedure from a saved environment." ;
274+ }
275+
276+ public Class <? extends CREThrowable >[] thrown () {
277+ return new Class []{CREIndexOverflowException .class };
278+ }
279+
280+ public boolean isRestricted () {
281+ return true ;
282+ }
283+
284+ public MSVersion since () {
285+ return MSVersion .V3_0_2 ;
286+ }
287+
288+ public Mixed exec (Target t , Environment env , Mixed ... args ) throws ConfigRuntimeException {
289+ String id = args [0 ].val ();
290+ String proc = args [1 ].val ();
291+
292+ Environment savedEnv ;
293+ synchronized (environmentMap ) {
294+ savedEnv = Optional .ofNullable (environmentMap .get (id )).orElseThrow (() -> {
295+ throw new CREIndexOverflowException ("No environment with this id \" " +id +"\" found" , t );
296+ });
220297 }
298+ GlobalEnv global = savedEnv .getEnv (GlobalEnv .class );
299+ Map <String , Procedure > procedures = global .GetProcs ();
300+
301+ return CBoolean .get (procedures .remove (proc ) != null );
302+ }
303+
304+ public Boolean runAsync () {
305+ return null ;
221306 }
222307 }
223308}
0 commit comments