@@ -452,6 +452,107 @@ void Switch::dump(std::ostream &out, const std::string &indent) {
452452 }
453453}
454454
455+ //
456+ // For
457+ //
458+
459+ bool For::declare (Module *module , Scope &scope, Error &error, bool is_lval) {
460+ if (m_is_var && m_init) {
461+ std::vector<Ref<Str>> names;
462+ if (auto assign = m_init->as <expr::Assignment>()) {
463+ auto lvalue = assign->lvalue ();
464+ if (auto id = lvalue->as <expr::Identifier>()) {
465+ names.emplace_back (id->name ());
466+ } else {
467+ error.tree = lvalue;
468+ error.message = " illegal left-value in assignment" ;
469+ return false ;
470+ }
471+ } else if (auto comp = m_init->as <expr::Compound>()) {
472+ for (size_t i = 0 , n = comp->expression_count (); i < n; i++) {
473+ auto expr = comp->expression (i);
474+ if (auto assign = expr->as <expr::Assignment>()) {
475+ auto lvalue = assign->lvalue ();
476+ if (auto id = lvalue->as <expr::Identifier>()) {
477+ names.emplace_back (id->name ());
478+ } else {
479+ error.tree = lvalue;
480+ error.message = " illegal left-value in assignment" ;
481+ return false ;
482+ }
483+ }
484+ }
485+ }
486+ auto s = scope.parent ();
487+ while (!s->is_root ()) s = s->parent ();
488+ for (const auto &name : names) {
489+ if (Var::is_fiber (name->str ())) {
490+ if (!check_reserved (name->str (), error)) return false ;
491+ s->declare_fiber_var (name, module );
492+ } else {
493+ s->declare_var (name);
494+ }
495+ }
496+ }
497+
498+ Tree::Scope s (Tree::Scope::LOOP, &scope);
499+ if (m_init && !m_init->declare (module , s, error, false )) return false ;
500+ if (m_cond && !m_cond->declare (module , s, error, false )) return false ;
501+ if (m_step && !m_step->declare (module , s, error, false )) return false ;
502+ if (m_body && !m_body->declare (module , s, error, false )) return false ;
503+
504+ return true ;
505+ }
506+
507+ void For::resolve (Module *module , Context &ctx, int l, Tree::LegacyImports *imports) {
508+ if (m_init) m_init->resolve (module , ctx, l, imports);
509+ if (m_cond) m_cond->resolve (module , ctx, l, imports);
510+ if (m_step) m_step->resolve (module , ctx, l, imports);
511+ if (m_body) m_body->resolve (module , ctx, l, imports);
512+ }
513+
514+ void For::execute (Context &ctx, Result &result) {
515+ Value val;
516+ if (m_init && !m_init->eval (ctx, val)) return ;
517+ for (;;) {
518+ if (m_cond) {
519+ if (!m_cond->eval (ctx, val)) return ;
520+ if (!val.to_boolean ()) break ;
521+ }
522+ if (m_body) {
523+ m_body->execute (ctx, result);
524+ if (!ctx.ok ()) return ;
525+ if (result.is_break ()) {
526+ if (result.label ) return ;
527+ break ;
528+ }
529+ if (result.is_continue ()) {
530+ if (m_step && !m_step->eval (ctx, val)) return ;
531+ continue ;
532+ }
533+ if (!result.is_done ()) return ;
534+ }
535+ if (m_step && !m_step->eval (ctx, val)) return ;
536+ }
537+ result.set_done ();
538+ }
539+
540+ bool For::check_reserved (const std::string &name, Error &error) {
541+ if (!Var::is_reserved (name)) return true ;
542+ error.tree = this ;
543+ error.message = " reserved variable name '" + name + " '" ;
544+ return false ;
545+ }
546+
547+ void For::dump (std::ostream &out, const std::string &indent) {
548+ auto indent2 = indent + " " ;
549+ out << indent << " for" << std::endl;
550+ out << indent << " init" << std::endl; if (m_init) m_init->dump (out, indent2);
551+ out << indent << " cond" << std::endl; if (m_cond) m_cond->dump (out, indent2);
552+ out << indent << " step" << std::endl; if (m_step) m_step->dump (out, indent2);
553+ out << indent << " body" << std::endl; if (m_body) m_body->dump (out, indent2);
554+ }
555+
455556//
456557// Break
457558//
@@ -463,7 +564,7 @@ bool Break::declare(Module *module, Scope &scope, Error &error, bool is_lval) {
463564 s = s->parent ();
464565 }
465566 } else {
466- while (s && s->kind () != Tree::Scope::SWITCH) {
567+ while (s && s->kind () != Tree::Scope::SWITCH && s-> kind () != Tree::Scope::LOOP ) {
467568 s = s->parent ();
468569 }
469570 }
0 commit comments