Skip to content

LiteralTime #109

@xmnlab

Description

@xmnlab

This is an initial idea from gpt, please feel free to use your own approach (maybe this idea is wrong):


Here’s a visit for LiteralTime you can drop into LLVMLiteIRVisitor.
It parses an ISO-ish time string (HH:MM or HH:MM:SS) and emits a constant struct { i32 hour, i32 minute, i32 second }. (Fractional seconds aren’t handled yet; easy to extend later to add a nanosecond field.)

from llvmlite import ir
from plum import dispatch

@dispatch  # type: ignore[no-redef]
def visit(self, node: astx.LiteralTime) -> None:
    """
    Lower a LiteralTime to LLVM IR.

    Representation:
      { i32 hour, i32 minute, i32 second }  -- emitted as a constant struct.

    Accepted formats:
      HH:MM
      HH:MM:SS

    Notes:
      - Fractional seconds (e.g., HH:MM:SS.sss) are not supported yet.
      - Basic range checks are enforced (00<=HH<=23, 00<=MM<=59, 00<=SS<=59).
    """
    s = node.value.strip()

    parts = s.split(":")
    if len(parts) not in (2, 3):
        raise Exception(
            f"LiteralTime: invalid time format '{node.value}'. "
            "Expected 'HH:MM' or 'HH:MM:SS'."
        )

    # Parse hour, minute
    try:
        hour = int(parts[0])
        minute = int(parts[1])
    except Exception as exc:
        raise Exception(f"LiteralTime: invalid hour/minute in '{node.value}'.") from exc

    # Parse second (optional)
    if len(parts) == 3:
        sec_part = parts[2]
        if "." in sec_part:
            # Not supported yet; reject clearly to avoid silent truncation.
            raise Exception(
                f"LiteralTime: fractional seconds not supported in '{node.value}'."
            )
        try:
            second = int(sec_part)
        except Exception as exc:
            raise Exception(f"LiteralTime: invalid seconds in '{node.value}'.") from exc
    else:
        second = 0

    # Range checks
    if not (0 <= hour <= 23):
        raise Exception(f"LiteralTime: hour out of range in '{node.value}'.")
    if not (0 <= minute <= 59):
        raise Exception(f"LiteralTime: minute out of range in '{node.value}'.")
    if not (0 <= second <= 59):
        raise Exception(f"LiteralTime: second out of range in '{node.value}'.")

    # Build constant struct { i32, i32, i32 }
    i32 = self._llvm.INT32_TYPE
    time_ty = ir.LiteralStructType([i32, i32, i32])
    const_time = ir.Constant(
        time_ty,
        [ir.Constant(i32, hour), ir.Constant(i32, minute), ir.Constant(i32, second)],
    )

    self.result_stack.append(const_time)

If you later want fractional seconds: switch to a 4-field struct { i32 h, i32 m, i32 s, i32 nanos } and parse the fractional part into nanoseconds (padding/truncating to 9 digits).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions