Files
py_enjoy/template/stat/ast/For.py
2026-02-27 14:37:10 +08:00

107 lines
3.3 KiB
Python

#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal For - For Directive
"""
from typing import Optional
from .Stat import Stat, StatList
from ..Scope import Scope
from ...Env import Env
class For(Stat):
"""For loop directive"""
def __init__(self, var_name: str, iter_expr: str, body: Stat):
"""
Initialize for directive
Args:
var_name: Loop variable name
iter_expr: Expression to iterate over
body: Loop body
"""
self._var_name = var_name
self._iter_expr = iter_expr
self._body = body
def exec(self, env: Env, scope: Scope, writer) -> None:
"""
Execute for loop
Args:
env: Template environment
scope: Execution scope
writer: Output writer
"""
try:
# Get the iterable from the expression
iterable = eval(self._iter_expr, {}, scope._data.copy())
# Convert iterable to list for easier manipulation
items = list(iterable)
size = len(items)
# Create a ForLoopInfo class to hold loop information
class ForLoopInfo:
def __init__(self, size, index, outer=None):
self._size = size
self._index = index
self._outer = outer
@property
def size(self):
return self._size
@property
def index(self):
return self._index
@property
def count(self):
return self._index + 1
@property
def first(self):
return self._index == 0
@property
def last(self):
return self._index == self._size - 1
@property
def odd(self):
return self._index % 2 == 0
@property
def even(self):
return self._index % 2 == 1
@property
def outer(self):
return self._outer
# Get outer for info if exists
outer_for = scope._data.get("for")
# Iterate over the items
for index, item in enumerate(items):
# Create for loop info
for_loop = ForLoopInfo(size, index, outer_for)
# Create a new scope for this iteration
loop_scope = Scope(scope._data.copy(), scope._shared_objects.copy())
loop_scope.set_parent(scope)
loop_scope._data[self._var_name] = item
loop_scope._data["for"] = for_loop
# Execute the loop body
if self._body:
self._body.exec(env, loop_scope, writer)
except Exception as e:
# Handle errors gracefully
writer.write(f"Error in for loop: {e}")
def __repr__(self) -> str:
return f"For(var={self._var_name}, expr={self._iter_expr})"