调整版本并做测试

This commit is contained in:
2026-02-27 17:10:54 +08:00
parent fa673138f6
commit 31be9d0e97
77 changed files with 679 additions and 25 deletions

View File

@@ -0,0 +1,172 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal Arith - Arithmetic Expression
"""
from .Expr import Expr
from decimal import Decimal, ROUND_HALF_UP
class Arith(Expr):
"""Arithmetic expression"""
ADD = "+"
SUB = "-"
MUL = "*"
DIV = "/"
MOD = "%"
_rounding_mode = ROUND_HALF_UP
def __init__(self, left: Expr, operator: str, right: Expr):
"""
Initialize arithmetic expression
Args:
left: Left expression
operator: Arithmetic operator
right: Right expression
"""
self._left = left
self._operator = operator
self._right = right
def eval(self, scope):
"""Evaluate arithmetic expression"""
left_val = self._left.eval(scope)
right_val = self._right.eval(scope)
# Handle None values
if left_val is None or right_val is None:
return None
# Convert to appropriate numeric types
left_num = self._to_number(left_val)
right_num = self._to_number(right_val)
if left_num is None or right_num is None:
return None
# Perform operation
if self._operator == Arith.ADD:
return left_num + right_num
elif self._operator == Arith.SUB:
return left_num - right_num
elif self._operator == Arith.MUL:
return left_num * right_num
elif self._operator == Arith.DIV:
if right_num == 0:
raise ZeroDivisionError("Division by zero")
return self._divide(left_num, right_num)
elif self._operator == Arith.MOD:
return left_num % right_num
else:
raise ValueError(f"Unknown operator: {self._operator}")
def _to_number(self, value):
"""Convert value to number"""
if isinstance(value, (int, float)):
return value
if isinstance(value, Decimal):
return value
if isinstance(value, str):
try:
if '.' in value:
return float(value)
else:
return int(value)
except ValueError:
return None
return None
def _divide(self, left, right):
"""Handle division with proper rounding"""
if isinstance(left, Decimal) or isinstance(right, Decimal):
result = Decimal(str(left)) / Decimal(str(right))
return result.quantize(Decimal('0.00000001'), rounding=self._rounding_mode)
else:
return left / right
@classmethod
def set_big_decimal_divide_rounding_mode(cls, rounding_mode):
"""Set rounding mode for decimal division"""
cls._rounding_mode = rounding_mode
def __repr__(self) -> str:
return f"Arith({self._left} {self._operator} {self._right})"
class Unary(Expr):
"""Unary expression (positive, negative, increment, decrement)"""
POSITIVE = "+"
NEGATIVE = "-"
NOT = "!"
def __init__(self, operator: str, expr: Expr):
"""
Initialize unary expression
Args:
operator: Unary operator
expr: Expression to operate on
"""
self._operator = operator
self._expr = expr
def eval(self, scope):
"""Evaluate unary expression"""
val = self._expr.eval(scope)
if self._operator == Unary.POSITIVE:
return +val if isinstance(val, (int, float)) else val
elif self._operator == Unary.NEGATIVE:
return -val if isinstance(val, (int, float)) else val
elif self._operator == Unary.NOT:
return not val
else:
raise ValueError(f"Unknown operator: {self._operator}")
def __repr__(self) -> str:
return f"Unary({self._operator}{self._expr})"
class IncDec(Expr):
"""Increment/Decrement expression"""
INC = "++"
DEC = "--"
def __init__(self, expr: Expr, operator: str, is_prefix: bool = True):
"""
Initialize increment/decrement
Args:
expr: Expression to increment/decrement
operator: INC or DEC
is_prefix: Whether this is prefix (++x) or postfix (x++)
"""
self._expr = expr
self._operator = operator
self._is_prefix = is_prefix
def eval(self, scope):
"""Evaluate increment/decrement"""
# This is a simplified implementation
# In a real implementation, this would modify the variable
current_val = self._expr.eval(scope)
if isinstance(current_val, int):
if self._operator == IncDec.INC:
return current_val + 1
else:
return current_val - 1
return current_val
def __repr__(self) -> str:
op_str = self._operator
if self._is_prefix:
return f"IncDec({op_str}{self._expr})"
else:
return f"IncDec({self._expr}{op_str})"

View File

@@ -0,0 +1,138 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal Compare - Comparison Expression
"""
from .Expr import Expr
class Compare(Expr):
"""Comparison expression"""
EQ = "=="
NE = "!="
GT = ">"
GTE = ">="
LT = "<"
LTE = "<="
def __init__(self, left: Expr, operator: str, right: Expr):
"""
Initialize comparison
Args:
left: Left expression
operator: Comparison operator
right: Right expression
"""
self._left = left
self._operator = operator
self._right = right
def eval(self, scope):
"""Evaluate comparison"""
left_val = self._left.eval(scope)
right_val = self._right.eval(scope)
# Handle None comparisons
if left_val is None and right_val is None:
return self._operator == Compare.EQ
if left_val is None or right_val is None:
return self._operator == Compare.NE
# Perform comparison based on operator
if self._operator == Compare.EQ:
return left_val == right_val
elif self._operator == Compare.NE:
return left_val != right_val
elif self._operator == Compare.GT:
return left_val > right_val
elif self._operator == Compare.GTE:
return left_val >= right_val
elif self._operator == Compare.LT:
return left_val < right_val
elif self._operator == Compare.LTE:
return left_val <= right_val
else:
raise ValueError(f"Unknown operator: {self._operator}")
@property
def operator(self) -> str:
"""Get operator"""
return self._operator
def __repr__(self) -> str:
return f"Compare({self._left} {self._operator} {self._right})"
class Logic(Expr):
"""Logical expression (and, or, not)"""
AND = "&&"
OR = "||"
NOT = "!"
def __init__(self, operator: str, *expressions: Expr):
"""
Initialize logical expression
Args:
operator: Logical operator
expressions: Expressions to operate on
"""
self._operator = operator
self._expressions = expressions
def eval(self, scope):
"""Evaluate logical expression"""
if self._operator == Logic.NOT:
# Unary NOT
if not self._expressions:
return True
return not self._expressions[0].eval(scope)
else:
# Binary AND/OR
results = [expr.eval(scope) for expr in self._expressions]
if self._operator == Logic.AND:
return all(results)
elif self._operator == Logic.OR:
return any(results)
else:
raise ValueError(f"Unknown operator: {self._operator}")
def __repr__(self) -> str:
expr_str = f" {self._operator} ".join(str(expr) for expr in self._expressions)
if self._operator == Logic.NOT:
return f"NOT({expr_str})"
return f"({expr_str})"
class Ternary(Expr):
"""Ternary conditional expression (condition ? true_val : false_val)"""
def __init__(self, condition: Expr, true_expr: Expr, false_expr: Expr):
"""
Initialize ternary expression
Args:
condition: Condition expression
true_expr: Expression when condition is true
false_expr: Expression when condition is false
"""
self._condition = condition
self._true_expr = true_expr
self._false_expr = false_expr
def eval(self, scope):
"""Evaluate ternary expression"""
cond_val = self._condition.eval(scope)
# Convert to boolean (handle None, 0, empty strings, etc.)
if cond_val:
return self._true_expr.eval(scope)
else:
return self._false_expr.eval(scope)
def __repr__(self) -> str:
return f"Ternary({self._condition} ? {self._true_expr} : {self._false_expr})"

View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal Const - Constant Expression
"""
from .Expr import Expr
class Const(Expr):
"""Constant value expression"""
def __init__(self, value):
"""
Initialize constant
Args:
value: Constant value
"""
self._value = value
def eval(self, scope):
"""Evaluate and return constant value"""
return self._value
def __repr__(self) -> str:
return f"Const({self._value})"
class NullExpr(Expr):
"""Null expression"""
def eval(self, scope):
"""Evaluate and return None"""
return None
def __repr__(self) -> str:
return "NullExpr()"
class Id(Expr):
"""Identifier expression (variable reference)"""
def __init__(self, name: str):
"""
Initialize identifier
Args:
name: Variable name
"""
self._name = name
def eval(self, scope):
"""Evaluate and return variable value"""
return scope.get(self._name)
@property
def name(self) -> str:
"""Get identifier name"""
return self._name
def __repr__(self) -> str:
return f"Id({self._name})"
class Map(Expr):
"""Map/dictionary expression"""
def __init__(self):
"""Initialize empty map"""
self._entries = []
def add_entry(self, key_expr: Expr, value_expr: Expr):
"""
Add map entry
Args:
key_expr: Key expression
value_expr: Value expression
"""
self._entries.append((key_expr, value_expr))
def eval(self, scope):
"""Evaluate and return map"""
result = {}
for key_expr, value_expr in self._entries:
key = key_expr.eval(scope)
value = value_expr.eval(scope)
if key is not None:
result[key] = value
return result
def __repr__(self) -> str:
return f"Map({len(self._entries)} entries)"
class Array(Expr):
"""Array/list expression"""
def __init__(self):
"""Initialize empty array"""
self._elements = []
def add_element(self, element_expr: Expr):
"""
Add array element
Args:
element_expr: Element expression
"""
self._elements.append(element_expr)
def eval(self, scope):
"""Evaluate and return array"""
return [expr.eval(scope) for expr in self._elements]
def __repr__(self) -> str:
return f"Array({len(self._elements)} elements)"
class RangeArray(Expr):
"""Range array expression (e.g., 1..10)"""
def __init__(self, start_expr: Expr, end_expr: Expr, inclusive: bool = True):
"""
Initialize range array
Args:
start_expr: Start expression
end_expr: End expression
inclusive: Whether end is inclusive
"""
self._start_expr = start_expr
self._end_expr = end_expr
self._inclusive = inclusive
def eval(self, scope):
"""Evaluate and return range array"""
start = self._start_expr.eval(scope)
end = self._end_expr.eval(scope)
if isinstance(start, int) and isinstance(end, int):
if self._inclusive:
return list(range(start, end + 1))
else:
return list(range(start, end))
# For non-integer ranges, return empty list
return []
def __repr__(self) -> str:
return f"RangeArray({self._start_expr}, {self._end_expr}, inclusive={self._inclusive})"

View File

@@ -0,0 +1,100 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal Expr - Expression Evaluation Base Class
"""
from typing import Any
from ...stat.Scope import Scope
from ...Env import Env
class Expr:
"""Base class for expression AST nodes"""
def eval(self, scope: Scope) -> Any:
"""
Evaluate expression
Args:
scope: Execution scope
Returns:
Expression result
"""
raise NotImplementedError("Expr.eval() must be implemented by subclasses")
def eval_expr_list(self, scope: Scope) -> list:
"""
Evaluate as expression list
Args:
scope: Execution scope
Returns:
List of expression results
"""
return [self.eval(scope)]
def __repr__(self) -> str:
return f"Expr({self.__class__.__name__})"
class ExprList(Expr):
"""Expression list containing multiple expressions"""
def __init__(self, expressions: list = None):
"""
Initialize expression list
Args:
expressions: List of expressions
"""
self._expressions = expressions or []
def add_expr(self, expr: Expr):
"""
Add expression to list
Args:
expr: Expression to add
"""
if expr:
self._expressions.append(expr)
def eval(self, scope: Scope) -> Any:
"""
Evaluate all expressions and return last result
Args:
scope: Execution scope
Returns:
Last expression result
"""
result = None
for expr in self._expressions:
result = expr.eval(scope)
return result
def eval_expr_list(self, scope: Scope) -> list:
"""
Evaluate all expressions and return list of results
Args:
scope: Execution scope
Returns:
List of results
"""
return [expr.eval(scope) for expr in self._expressions]
def get_expressions(self) -> list:
"""Get all expressions"""
return self._expressions.copy()
def __len__(self) -> int:
"""Get number of expressions"""
return len(self._expressions)
def __repr__(self) -> str:
return f"ExprList({len(self._expressions)} expressions)"

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal FieldKeyBuilder - Field Key Builder
"""
class FieldKeyBuilder:
"""Field key builder for field access"""
def __init__(self):
"""Initialize field key builder"""
pass
def build_field_key(self, field_name: str) -> str:
"""
Build field key
Args:
field_name: Field name
Returns:
Field key
"""
return field_name
def __repr__(self) -> str:
return "FieldKeyBuilder()"

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal FieldKit - Field Access Utilities
"""
class FieldKit:
"""Field access utilities"""
@staticmethod
def get_field(obj, field_name: str):
"""
Get field value from object
Args:
obj: Object to get field from
field_name: Field name
Returns:
Field value or None
"""
if obj is None:
return None
# Try attribute access
if hasattr(obj, field_name):
return getattr(obj, field_name)
# Try dictionary access
if isinstance(obj, dict) and field_name in obj:
return obj[field_name]
return None
@staticmethod
def set_field(obj, field_name: str, value):
"""
Set field value on object
Args:
obj: Object to set field on
field_name: Field name
value: Value to set
Returns:
True if successful, False otherwise
"""
if obj is None:
return False
# Try attribute access
if hasattr(obj, field_name):
setattr(obj, field_name, value)
return True
# Try dictionary access
if isinstance(obj, dict):
obj[field_name] = value
return True
return False
def __repr__(self) -> str:
return "FieldKit()"

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal MethodKit - Method Access Utilities
"""
class MethodKit:
"""Method access utilities"""
@staticmethod
def get_method(obj, method_name: str, *args):
"""
Get method from object
Args:
obj: Object to get method from
method_name: Method name
args: Method arguments
Returns:
Method or None
"""
if obj is None:
return None
# Try attribute access
if hasattr(obj, method_name):
method = getattr(obj, method_name)
if callable(method):
return method
return None
@staticmethod
def invoke_method(obj, method_name: str, *args):
"""
Invoke method on object
Args:
obj: Object to invoke method on
method_name: Method name
args: Method arguments
Returns:
Method result or None
"""
method = MethodKit.get_method(obj, method_name)
if method:
try:
return method(*args)
except:
return None
return None
def __repr__(self) -> str:
return "MethodKit()"

View File

@@ -0,0 +1,121 @@
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal SharedMethodKit - Shared Method Kit
"""
from typing import Dict, List, Any, Optional
class SharedMethodKit:
"""Shared method kit for template functions"""
def __init__(self):
"""Initialize shared method kit"""
self._shared_methods: Dict[str, List[Any]] = {}
def add_shared_method(self, obj: Any):
"""
Add shared methods from object
Args:
obj: Object with methods to add
"""
if obj is None:
return
# Get all methods from object
import inspect
for name, method in inspect.getmembers(obj, predicate=inspect.ismethod):
if not name.startswith('_'):
if name not in self._shared_methods:
self._shared_methods[name] = []
self._shared_methods[name].append(method)
def add_shared_method_from_class(self, clazz):
"""
Add shared methods from class
Args:
clazz: Class with methods to add
"""
if clazz is None:
return
# Get all methods from class
import inspect
for name, method in inspect.getmembers(clazz, predicate=inspect.isfunction):
if not name.startswith('_'):
if name not in self._shared_methods:
self._shared_methods[name] = []
self._shared_methods[name].append(method)
def add_shared_static_method(self, clazz):
"""
Add shared static methods from class
Args:
clazz: Class with static methods to add
"""
if clazz is None:
return
# Get all static methods from class
import inspect
for name, method in inspect.getmembers(clazz, predicate=inspect.isfunction):
if not name.startswith('_'):
if name not in self._shared_methods:
self._shared_methods[name] = []
self._shared_methods[name].append(method)
def remove_shared_method(self, method_name: str):
"""
Remove shared method by name
Args:
method_name: Method name to remove
"""
if method_name in self._shared_methods:
del self._shared_methods[method_name]
def get_shared_method(self, method_name: str) -> Optional[Any]:
"""
Get shared method by name
Args:
method_name: Method name to get
Returns:
Shared method or None
"""
if method_name in self._shared_methods:
methods = self._shared_methods[method_name]
if methods:
return methods[0]
return None
def get_shared_methods(self, method_name: str) -> List[Any]:
"""
Get all shared methods with given name
Args:
method_name: Method name
Returns:
List of shared methods
"""
return self._shared_methods.get(method_name, [])
def has_shared_method(self, method_name: str) -> bool:
"""
Check if shared method exists
Args:
method_name: Method name
Returns:
True if method exists, False otherwise
"""
return method_name in self._shared_methods and self._shared_methods[method_name]
def __repr__(self) -> str:
return f"SharedMethodKit({len(self._shared_methods)} methods)"

View File

@@ -0,0 +1,20 @@
# Export expression AST classes
from .Expr import Expr, ExprList
from .Const import Const, NullExpr, Id, Map, Array, RangeArray
from .Compare import Compare, Logic, Ternary
from .Arith import Arith, Unary, IncDec
from .SharedMethodKit import SharedMethodKit
from .FieldKit import FieldKit
from .FieldKeyBuilder import FieldKeyBuilder
from .MethodKit import MethodKit
__all__ = [
'Expr', 'ExprList',
'Const', 'NullExpr', 'Id', 'Map', 'Array', 'RangeArray',
'Compare', 'Logic', 'Ternary',
'Arith', 'Unary', 'IncDec',
'SharedMethodKit',
'FieldKit',
'FieldKeyBuilder',
'MethodKit'
]