@@ -35,6 +35,8 @@ public class PiccodeClosure implements PiccodeValue {
3535 public int line , column ;
3636 public Integer frame = null ;
3737
38+ public List <String > annotations = new ArrayList <>();
39+
3840 public PiccodeClosure (List <Ast > params , Map <String , PiccodeValue > appliedArgs , int positionalIndex , Ast body ) {
3941 this .params = params == null ? new ArrayList <>() : params ;
4042 this .appliedArgs = appliedArgs ;
@@ -61,6 +63,7 @@ public PiccodeValue call(PiccodeValue arg) {
6163 }
6264
6365 var result = new PiccodeClosure (params , newArgs , positionalIndex + 1 , body );
66+ result .annotations = annotations ;
6467 result .creator = creator ;
6568 result .frame = frame ;
6669 result .callSite = callSite ;
@@ -105,6 +108,7 @@ public PiccodeValue callNamed(String name, PiccodeValue arg) {
105108 newArgs .put (name , arg );
106109
107110 var result = new PiccodeClosure (params , newArgs , positionalIndex + 1 , body );
111+ result .annotations = annotations ;
108112 result .creator = creator ;
109113 result .frame = frame ;
110114 result .callSite = callSite ;
@@ -125,48 +129,56 @@ public PiccodeValue evaluateIfReady() {
125129 }
126130 }
127131 }
128- var ctx = frame == null
129- ? Context .top
130- : Context .getContextAt (frame );
131- ctx .pushStackFrame (creator );
132- for (Ast param : params ) {
133- PiccodeValue val = param instanceof Arg arg
134- ? appliedArgs .getOrDefault (
135- arg .name ,
136- arg .def_val != null ? arg .def_val .execute (frame ) : null
137- ) : param .execute (frame );
132+ return Ast .safeExecute (frame , creator , ($_unused_$ ) -> {
133+ for (Ast param : params ) {
134+ var ctx = frame == null
135+ ? Context .top
136+ : Context .getContextAt (frame );
137+
138+
139+ PiccodeValue val = param instanceof Arg arg
140+ ? appliedArgs .getOrDefault (
141+ arg .name ,
142+ arg .def_val != null ? arg .def_val .execute (frame ) : null
143+ ) : param .execute (frame );
138144
139- if (param instanceof Arg arg ) {
140- if (arg .export && !(val instanceof PiccodeObject )) {
141- throw new PiccodeException (param .file , param .line , param .column , "Cannot export fields of a value that is not an object. Found type " + Chalk .on (val .type ()).red ());
142- } else if (arg .export && val instanceof PiccodeObject obj ) {
143- for (var kv : obj .obj .entrySet ()) {
144- var name = kv .getKey ();
145- var value = kv .getValue ();
146- ctx .putLocal (name , value );
145+ if (param instanceof Arg arg ) {
146+ if (arg .export && !(val instanceof PiccodeObject )) {
147+ throw new PiccodeException (param .file , param .line , param .column , "Cannot export fields of a value that is not an object. Found type " + Chalk .on (val .type ()).red ());
148+ } else if (arg .export && val instanceof PiccodeObject obj ) {
149+ for (var kv : obj .obj .entrySet ()) {
150+ var name = kv .getKey ();
151+ var value = kv .getValue ();
152+ ctx .putLocal (name , value );
153+ }
154+ } else {
155+ ctx .putLocal (arg .name , val );
147156 }
148- } else {
149- ctx .putLocal (arg .name , val );
150157 }
151158 }
152- }
153159
154- try {
155- var result = body .execute (frame );
156- ctx .dropStackFrame ();
157-
158- return result ;
159- } catch (PiccodeReturnException ret ) {
160- ctx .dropStackFrame ();
161- return ret .value ;
162- } catch (StackOverflowError se ) {
163- ctx .dropStackFrame ();
164- var err = new PiccodeException (callSiteFile , callSite .line , callSite .col , "Stack overflow" );
165- err .frame = frame ;
166- var note = new PiccodeException (file , line , column , "Stack overflow error most likely occured when you called the function below. " );
167- err .addNote (note );
168- throw err ;
169- }
160+
161+ try {
162+ if (!annotations .isEmpty ()) {
163+ for (var annotation : annotations ) {
164+ if (!Context .hasAnnotation (annotation )) {
165+ throw new PiccodeException (file , line , column , "Annotation `" + Chalk .on (annotation ).red () + "` does not exist." );
166+ }
167+ // TODO: Allow mutiple nested annotations
168+ var fx = Context .getAnnotation (annotation );
169+ return fx .apply (frame , body );
170+ }
171+ }
172+ var result = body .execute (frame );
173+ return result ;
174+ } catch (StackOverflowError se ) {
175+ var err = new PiccodeException (callSiteFile , callSite .line , callSite .col , "Stack overflow" );
176+ err .frame = frame ;
177+ var note = new PiccodeException (file , line , column , "Stack overflow error most likely occured when you called the function below. " );
178+ err .addNote (note );
179+ throw err ;
180+ }
181+ });
170182 }
171183
172184 @ Override
@@ -212,15 +224,14 @@ private void createWhenExpression(Integer frame) {
212224 cases .add (when );
213225 }
214226
215-
216227 var args = clause .getArgs ();
217228 var cond = args .size () == 1 ? args .getFirst () : new TupleAst (args );
218-
229+
219230 var errNode = new ErrorNodeExpr ("Inexhaustive when expression: no pattern matched: when " + cond + " { ... }" );
220231 errNode .file = file ;
221232 errNode .line = line ;
222233 errNode .column = column ;
223-
234+
224235 var generalCaseBody = isMatched (clause .body , cases )
225236 ? errNode
226237 : clause .body ;
@@ -290,7 +301,7 @@ private void computeStableClause() {
290301 newParams .addLast (arg );
291302 }
292303 }
293- }
304+ }
294305
295306 clauses .add (new ClauseAst (params , body ));
296307 params = newParams ;
0 commit comments