@@ -7,7 +7,7 @@ import { AiScriptError, NonAiScriptError, AiScriptNamespaceError, AiScriptIndexO
77import * as Ast from '../node.js' ;
88import { Scope } from './scope.js' ;
99import { std } from './lib/std.js' ;
10- import { RETURN , unWrapRet , BREAK , CONTINUE , assertValue , isControl , type Control } from './control.js' ;
10+ import { RETURN , unWrapRet , BREAK , CONTINUE , assertValue , isControl , type Control , unWrapLabeledBreak } from './control.js' ;
1111import { assertNumber , assertString , assertFunction , assertBoolean , assertObject , assertArray , eq , isObject , isArray , expectAny , reprValue , isFunction } from './util.js' ;
1212import { NULL , FN_NATIVE , BOOL , NUM , STR , ARR , OBJ , FN , ERROR } from './value.js' ;
1313import { getPrimProp } from './primitive-props.js' ;
@@ -371,7 +371,7 @@ export class Interpreter {
371371 }
372372 assertBoolean ( cond ) ;
373373 if ( cond . value ) {
374- return this . _evalClause ( node . then , scope , callStack ) ;
374+ return unWrapLabeledBreak ( await this . _evalClause ( node . then , scope , callStack ) , node . label ) ;
375375 }
376376 for ( const elseif of node . elseif ) {
377377 const cond = await this . _eval ( elseif . cond , scope , callStack ) ;
@@ -380,11 +380,11 @@ export class Interpreter {
380380 }
381381 assertBoolean ( cond ) ;
382382 if ( cond . value ) {
383- return this . _evalClause ( elseif . then , scope , callStack ) ;
383+ return unWrapLabeledBreak ( await this . _evalClause ( elseif . then , scope , callStack ) , node . label ) ;
384384 }
385385 }
386386 if ( node . else ) {
387- return this . _evalClause ( node . else , scope , callStack ) ;
387+ return unWrapLabeledBreak ( await this . _evalClause ( node . else , scope , callStack ) , node . label ) ;
388388 }
389389 return NULL ;
390390 }
@@ -400,11 +400,11 @@ export class Interpreter {
400400 return q ;
401401 }
402402 if ( eq ( about , q ) ) {
403- return await this . _evalClause ( qa . a , scope , callStack ) ;
403+ return unWrapLabeledBreak ( await this . _evalClause ( qa . a , scope , callStack ) , node . label ) ;
404404 }
405405 }
406406 if ( node . default ) {
407- return await this . _evalClause ( node . default , scope , callStack ) ;
407+ return unWrapLabeledBreak ( await this . _evalClause ( node . default , scope , callStack ) , node . label ) ;
408408 }
409409 return NULL ;
410410 }
@@ -414,7 +414,14 @@ export class Interpreter {
414414 while ( true ) {
415415 const v = await this . _run ( node . statements , scope . createChildScope ( ) , callStack ) ;
416416 if ( v . type === 'break' ) {
417+ if ( v . label != null && v . label !== node . label ) {
418+ return v ;
419+ }
417420 break ;
421+ } else if ( v . type === 'continue' ) {
422+ if ( v . label != null && v . label !== node . label ) {
423+ return v ;
424+ }
418425 } else if ( v . type === 'return' ) {
419426 return v ;
420427 }
@@ -432,7 +439,14 @@ export class Interpreter {
432439 for ( let i = 0 ; i < times . value ; i ++ ) {
433440 const v = await this . _evalClause ( node . for , scope , callStack ) ;
434441 if ( v . type === 'break' ) {
442+ if ( v . label != null && v . label !== node . label ) {
443+ return v ;
444+ }
435445 break ;
446+ } else if ( v . type === 'continue' ) {
447+ if ( v . label != null && v . label !== node . label ) {
448+ return v ;
449+ }
436450 } else if ( v . type === 'return' ) {
437451 return v ;
438452 }
@@ -456,7 +470,14 @@ export class Interpreter {
456470 } ] ,
457471 ] ) ) , callStack ) ;
458472 if ( v . type === 'break' ) {
473+ if ( v . label != null && v . label !== node . label ) {
474+ return v ;
475+ }
459476 break ;
477+ } else if ( v . type === 'continue' ) {
478+ if ( v . label != null && v . label !== node . label ) {
479+ return v ;
480+ }
460481 } else if ( v . type === 'return' ) {
461482 return v ;
462483 }
@@ -476,7 +497,14 @@ export class Interpreter {
476497 this . define ( eachScope , node . var , item , false ) ;
477498 const v = await this . _eval ( node . for , eachScope , callStack ) ;
478499 if ( v . type === 'break' ) {
500+ if ( v . label != null && v . label !== node . label ) {
501+ return v ;
502+ }
479503 break ;
504+ } else if ( v . type === 'continue' ) {
505+ if ( v . label != null && v . label !== node . label ) {
506+ return v ;
507+ }
480508 } else if ( v . type === 'return' ) {
481509 return v ;
482510 }
@@ -695,7 +723,7 @@ export class Interpreter {
695723 }
696724
697725 case 'block' : {
698- return this . _run ( node . statements , scope . createChildScope ( ) , callStack ) ;
726+ return unWrapLabeledBreak ( await this . _run ( node . statements , scope . createChildScope ( ) , callStack ) , node . label ) ;
699727 }
700728
701729 case 'exists' : {
@@ -728,13 +756,21 @@ export class Interpreter {
728756 }
729757
730758 case 'break' : {
759+ let val : Value | undefined ;
760+ if ( node . expr != null ) {
761+ const valueOrControl = await this . _eval ( node . expr , scope , callStack ) ;
762+ if ( isControl ( valueOrControl ) ) {
763+ return valueOrControl ;
764+ }
765+ val = valueOrControl ;
766+ }
731767 this . log ( 'block:break' , { scope : scope . name } ) ;
732- return BREAK ( ) ;
768+ return BREAK ( node . label , val ) ;
733769 }
734770
735771 case 'continue' : {
736772 this . log ( 'block:continue' , { scope : scope . name } ) ;
737- return CONTINUE ( ) ;
773+ return CONTINUE ( node . label ) ;
738774 }
739775
740776 case 'ns' : {
0 commit comments