107 lines
3.3 KiB
Python
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})"
|