"""
Symbol table management for the yapCAD DSL type checker.
Provides scoped symbol tables for tracking variable definitions,
function signatures, and type information during type checking.
"""
from dataclasses import dataclass, field
from typing import Optional, Dict, List, Callable, Any, Tuple
from enum import Enum, auto
from .types import (
Type, FunctionType, ListType, ERROR, UNKNOWN,
INT, FLOAT, BOOL, STRING,
POINT, POINT2D, POINT3D, VECTOR, VECTOR2D, VECTOR3D, TRANSFORM,
LINE_SEGMENT, ARC, CIRCLE, ELLIPSE, PARABOLA, HYPERBOLA,
CATMULLROM, NURBS, BEZIER,
PATH2D, PATH3D, PROFILE2D, REGION2D, LOOP3D,
SURFACE, SHELL, SOLID, DICT,
make_list_type, make_optional_type,
)
from .tokens import SourceSpan
[docs]
class SymbolKind(Enum):
"""The kind of symbol being tracked."""
VARIABLE = auto()
PARAMETER = auto()
FUNCTION = auto()
COMMAND = auto()
MODULE = auto()
[docs]
@dataclass
class Symbol:
"""A symbol in the symbol table."""
name: str
kind: SymbolKind
type: Type
span: Optional[SourceSpan] = None # Where it was defined
is_mutable: bool = False
has_python_block: bool = False # Commands with Python blocks
[docs]
@dataclass
class FunctionSignature:
"""Type signature for a function or built-in."""
name: str
params: List[Tuple[str, Type, Optional[Any]]] # (name, type, default)
return_type: Type
is_method: bool = False # True for methods like curve.at()
is_variadic: bool = False # True for functions that accept list<T> as well
[docs]
@dataclass
class Scope:
"""A single scope in the scope stack."""
symbols: Dict[str, Symbol] = field(default_factory=dict)
parent: Optional["Scope"] = None
name: str = "" # For debugging: "command MAKE_GEAR", "for loop", etc.
[docs]
def define(self, symbol: Symbol) -> None:
"""Define a symbol in this scope."""
self.symbols[symbol.name] = symbol
[docs]
def lookup_local(self, name: str) -> Optional[Symbol]:
"""Look up a symbol in this scope only."""
return self.symbols.get(name)
[docs]
def lookup(self, name: str) -> Optional[Symbol]:
"""Look up a symbol in this scope or any parent scope."""
symbol = self.symbols.get(name)
if symbol is not None:
return symbol
if self.parent is not None:
return self.parent.lookup(name)
return None
[docs]
class SymbolTable:
"""
Manages scopes and symbol definitions for type checking.
Provides:
- Nested scope management (push/pop)
- Symbol definition and lookup
- Built-in function registry
"""
def __init__(self):
# Global scope contains built-in functions and types
self._global_scope = Scope(name="global")
self._current_scope = self._global_scope
# Built-in function signatures
self._builtins: Dict[str, FunctionSignature] = {}
# Initialize built-ins
self._init_builtins()
def _init_builtins(self) -> None:
"""Initialize built-in function signatures."""
# Tier 1: Point and Vector constructors
self._register_builtin("point", [
("x", FLOAT, None),
("y", FLOAT, None),
("z", FLOAT, "optional"), # Optional - presence determines 2D/3D, default 0.0
], POINT)
# Convenience constructor for 2D points (z=0)
self._register_builtin("point2d", [
("x", FLOAT, None),
("y", FLOAT, None),
], POINT2D)
self._register_builtin("vector", [
("dx", FLOAT, None),
("dy", FLOAT, None),
("dz", FLOAT, None),
], VECTOR)
# Convenience constructor for 2D vectors (dz=0)
self._register_builtin("vector2d", [
("dx", FLOAT, None),
("dy", FLOAT, None),
], VECTOR2D)
# Solid transformation functions (translate, rotate, scale solids directly)
self._register_builtin("translate", [
("s", SOLID, None),
("x", FLOAT, None),
("y", FLOAT, None),
("z", FLOAT, None),
], SOLID)
self._register_builtin("rotate", [
("s", SOLID, None),
("x", FLOAT, None),
("y", FLOAT, None),
("z", FLOAT, None),
], SOLID)
self._register_builtin("scale", [
("s", SOLID, None),
("x", FLOAT, None),
("y", FLOAT, None),
("z", FLOAT, None),
], SOLID)
# Transform constructors (for advanced use - create transform matrices)
self._register_builtin("translate_xform", [("v", VECTOR, None)], TRANSFORM)
self._register_builtin("rotate_xform", [
("axis", VECTOR3D, None),
("angle", FLOAT, None),
], TRANSFORM)
self._register_builtin("rotate_2d", [("angle", FLOAT, None)], TRANSFORM)
self._register_builtin("scale_xform", [("factors", VECTOR, None)], TRANSFORM)
self._register_builtin("scale_uniform", [("factor", FLOAT, None)], TRANSFORM)
self._register_builtin("mirror", [("s", SOLID, None), ("plane_normal", VECTOR3D, None)], SOLID)
self._register_builtin("mirror_2d", [("axis", VECTOR2D, None)], TRANSFORM)
self._register_builtin("mirror_y", [], TRANSFORM) # Convenience
self._register_builtin("identity_transform", [], TRANSFORM)
# Tier 2: Curve constructors
self._register_builtin("line", [
("start", POINT, None),
("end", POINT, None),
], LINE_SEGMENT)
self._register_builtin("arc", [
("center", POINT, None),
("radius", FLOAT, None),
("start_angle", FLOAT, None),
("end_angle", FLOAT, None),
], ARC)
self._register_builtin("circle", [
("center", POINT, None),
("radius", FLOAT, None),
], CIRCLE)
self._register_builtin("ellipse", [
("center", POINT, None),
("semi_major", FLOAT, None),
("semi_minor", FLOAT, None),
("rotation", FLOAT, "optional"),
("start", FLOAT, "optional"),
("end", FLOAT, "optional"),
], ELLIPSE)
self._register_builtin("bezier", [
("control_points", make_list_type(POINT), None),
], BEZIER)
self._register_builtin("catmullrom", [
("points", make_list_type(POINT), None),
("closed", BOOL, "optional"), # default false
("alpha", FLOAT, "optional"), # default 0.5
], CATMULLROM)
self._register_builtin("nurbs", [
("points", make_list_type(POINT), None),
("weights", make_list_type(FLOAT), "optional"), # default all 1.0
("degree", INT, "optional"), # default 3
], NURBS)
# Curve sampling functions
self._register_builtin("sample_curve", [
("curve", UNKNOWN, None), # Any curve type
("t", FLOAT, None),
], POINT)
self._register_builtin("sample_curve_n", [
("curve", UNKNOWN, None),
("n", INT, None),
], make_list_type(POINT))
self._register_builtin("curve_length", [
("curve", UNKNOWN, None),
], FLOAT)
# Tier 3: Path/Region operations
self._register_builtin("path", [
("segments", make_list_type(UNKNOWN), None), # list of curves
], PATH2D) # Returns path2d or path3d based on input
self._register_builtin("join", [
("p1", PATH2D, None),
("p2", PATH2D, None),
], PATH2D)
# Path3D constructors for sweep operations (variadic)
self._register_builtin("make_path3d", [
("segment", PATH3D, None),
], PATH3D, is_variadic=True)
self._register_builtin("path3d_line", [
("start", POINT3D, None),
("end", POINT3D, None),
], PATH3D)
self._register_builtin("path3d_arc", [
("center", POINT3D, None),
("start", POINT3D, None),
("end", POINT3D, None),
("normal", VECTOR3D, None),
], PATH3D)
# Arc with auto-computed normal from geometry
# flip=false: normal = (center->start) x (center->end), takes shorter arc
# flip=true: negated normal, takes longer arc (opposite direction)
self._register_builtin("path3d_arc_auto", [
("center", POINT3D, None),
("start", POINT3D, None),
("end", POINT3D, None),
("flip", BOOL, None),
], PATH3D)
self._register_builtin("close", [("p", PROFILE2D, None)], REGION2D)
self._register_builtin("closeC0", [("p", PROFILE2D, None)], REGION2D)
self._register_builtin("closeC1", [("p", PROFILE2D, None)], REGION2D)
self._register_builtin("rectangle", [
("width", FLOAT, None),
("height", FLOAT, None),
("center", POINT2D, "optional"),
], REGION2D)
self._register_builtin("regular_polygon", [
("n", INT, None),
("radius", FLOAT, None),
("center", POINT2D, "optional"),
], REGION2D)
# Polygon from points
self._register_builtin("polygon", [
("points", make_list_type(POINT), None),
], REGION2D)
# Disk (filled circle as polygon)
self._register_builtin("disk", [
("center", POINT, None),
("radius", FLOAT, None),
("segments", INT, "optional"), # default 64
], REGION2D)
# 2D Boolean operations
self._register_builtin("union2d", [
("a", REGION2D, None),
("b", REGION2D, None),
], REGION2D)
self._register_builtin("difference2d", [
("a", REGION2D, None),
("b", REGION2D, None),
], REGION2D)
self._register_builtin("intersection2d", [
("a", REGION2D, None),
("b", REGION2D, None),
], REGION2D)
# Phase 3: 2D boolean aggregation functions
self._register_builtin("union2d_all", [
("regions", make_list_type(REGION2D), None),
], REGION2D)
self._register_builtin("difference2d_all", [
("base", REGION2D, None),
("tools", make_list_type(REGION2D), None),
], REGION2D)
self._register_builtin("intersection2d_all", [
("regions", make_list_type(REGION2D), None),
], REGION2D)
# Path2D construction
self._register_builtin("make_path2d", [
("curves", make_list_type(UNKNOWN), None),
], PATH2D)
self._register_builtin("close_path", [
("path", PATH2D, None),
], REGION2D)
# Region from spline
self._register_builtin("region_from_spline", [
("spline", UNKNOWN, None),
("segments", INT, "optional"),
], REGION2D)
# Tier 4: Surface operations
self._register_builtin("planar_surface", [
("boundary", LOOP3D, None),
], SURFACE)
self._register_builtin("cylindrical_surface", [
("axis", VECTOR3D, None),
("radius", FLOAT, None),
("height", FLOAT, None),
], SURFACE)
self._register_builtin("loft_surface", [
("profiles", make_list_type(PATH3D), None),
], SURFACE)
self._register_builtin("shell", [
("surfaces", make_list_type(SURFACE), None),
], SHELL)
# Tier 5: Solid operations
self._register_builtin("extrude", [
("profile", REGION2D, None),
("height", FLOAT, None),
("direction", VECTOR3D, "optional"),
], SOLID)
self._register_builtin("revolve", [
("profile", REGION2D, None),
("axis", VECTOR3D, None),
("angle", FLOAT, None),
], SOLID)
self._register_builtin("sweep", [
("profile", REGION2D, None),
("spine", PATH3D, None),
], SOLID)
self._register_builtin("sweep_hollow", [
("outer_profile", REGION2D, None),
("inner_profile", REGION2D, None),
("spine", PATH3D, None),
], SOLID)
self._register_builtin("sweep_adaptive", [
("profile", REGION2D, None),
("spine", PATH3D, None),
("threshold", FLOAT, None), # Angle in degrees
], SOLID)
self._register_builtin("sweep_adaptive_hollow", [
("outer_profile", REGION2D, None),
("inner_profiles", REGION2D, None), # Single region2d or list
("spine", PATH3D, None),
("threshold", FLOAT, None),
], SOLID)
# Frenet frame variants - profile follows natural curvature
self._register_builtin("sweep_adaptive_frenet", [
("profile", REGION2D, None),
("spine", PATH3D, None),
("threshold", FLOAT, None),
], SOLID)
self._register_builtin("sweep_adaptive_hollow_frenet", [
("outer_profile", REGION2D, None),
("inner_profiles", REGION2D, None),
("spine", PATH3D, None),
("threshold", FLOAT, None),
], SOLID)
self._register_builtin("loft", [
("profiles", make_list_type(REGION2D), None),
], SOLID)
self._register_builtin("box", [
("width", FLOAT, None),
("depth", FLOAT, None),
("height", FLOAT, None),
], SOLID)
self._register_builtin("cylinder", [
("radius", FLOAT, None),
("height", FLOAT, None),
], SOLID)
self._register_builtin("sphere", [
("radius", FLOAT, None),
], SOLID)
self._register_builtin("oblate_spheroid", [
("equatorial_diameter", FLOAT, None),
("oblateness", FLOAT, None),
], SOLID)
self._register_builtin("cone", [
("radius1", FLOAT, None),
("radius2", FLOAT, None),
("height", FLOAT, None),
], SOLID)
# Involute gear - creates a proper gear profile
self._register_builtin("involute_gear", [
("teeth", INT, None),
("module_mm", FLOAT, None),
("pressure_angle", FLOAT, None),
("face_width", FLOAT, None),
], SOLID)
# Herringbone gear - double-helix gear with smooth tooth surfaces
self._register_builtin("herringbone_gear", [
("teeth", INT, None),
("module_mm", FLOAT, None),
("face_width", FLOAT, None),
("helix_angle", FLOAT, None),
], SOLID)
# Sun gear with integrated hub - optimized to avoid expensive boolean
self._register_builtin("sun_gear_with_hub", [
("teeth", INT, None),
("module_mm", FLOAT, None),
("face_width", FLOAT, None),
("helix_angle", FLOAT, None),
("hub_diameter", FLOAT, None),
("hub_height", FLOAT, None),
("bolt_circle", FLOAT, None),
("num_bolts", INT, None),
("bolt_hole_diameter", FLOAT, None),
], SOLID)
# Phase 2 geometry primitives
self._register_builtin("dodecahedron", [
("diameter", FLOAT, None),
], SOLID)
self._register_builtin("tube", [
("outer_diameter", FLOAT, None),
("wall_thickness", FLOAT, None),
("length", FLOAT, None),
], SOLID)
self._register_builtin("conic_tube", [
("bottom_od", FLOAT, None),
("top_od", FLOAT, None),
("wall_thickness", FLOAT, None),
("length", FLOAT, None),
], SOLID)
self._register_builtin("spherical_shell", [
("outer_diameter", FLOAT, None),
("wall_thickness", FLOAT, None),
], SOLID)
self._register_builtin("helical_extrude", [
("profile", REGION2D, None),
("height", FLOAT, None),
("twist_angle", FLOAT, None),
], SOLID)
# Phase 3 text support
self._register_builtin("text_solid", [
("text", STRING, None),
("height", FLOAT, None),
("depth", FLOAT, None),
("spacing", FLOAT, None),
], SOLID)
self._register_builtin("engrave_text", [
("target", SOLID, None),
("text", STRING, None),
("position", VECTOR3D, None),
("normal", VECTOR3D, None),
("height", FLOAT, None),
("depth", FLOAT, None),
("spacing", FLOAT, None),
], SOLID)
self._register_builtin("text_width", [
("text", STRING, None),
("height", FLOAT, None),
("spacing", FLOAT, None),
], FLOAT)
# Phase 4 path utilities & manufacturing
self._register_builtin("path3d_eval", [
("path", PATH3D, None),
("t", FLOAT, None),
], POINT3D) # Returns point (tangent available via separate call if needed)
self._register_builtin("path3d_length", [
("path", PATH3D, None),
], FLOAT)
self._register_builtin("split_solid", [
("s", SOLID, None),
("plane_point", POINT3D, None),
("plane_normal", VECTOR3D, None),
], SOLID) # Returns list but typed as SOLID for now (first half)
# Planet gear with integrated hub - eliminates tooth root holes
# Hub fills from bore to dedendum radius, full face width
self._register_builtin("planet_gear_with_hub", [
("teeth", INT, None),
("module_mm", FLOAT, None),
("face_width", FLOAT, None),
("helix_angle", FLOAT, None),
("bore_diameter", FLOAT, None),
], SOLID)
# Fasteners - hex bolts and nuts from catalog
# Metric fasteners (ISO 4014/4017 bolts, ISO 4032 nuts)
self._register_builtin("metric_hex_bolt", [
("size", STRING, None), # e.g., "M8", "M10"
("length", FLOAT, None), # shank length in mm
], SOLID)
self._register_builtin("metric_hex_nut", [
("size", STRING, None), # e.g., "M8", "M10"
], SOLID)
# Unified fasteners (ASME B18.2.1 bolts, ASME B18.2.2 nuts)
self._register_builtin("unified_hex_bolt", [
("size", STRING, None), # e.g., "1/4-20", "1/2-13"
("length", FLOAT, None), # shank length in inches
], SOLID)
self._register_builtin("unified_hex_nut", [
("size", STRING, None), # e.g., "1/4-20", "1/2-13"
], SOLID)
# Text solid generation - 3D extruded text
self._register_builtin("text_solid", [
("text", STRING, None), # Text string to render
("height", FLOAT, None), # Character height in mm
("depth", FLOAT, None), # Extrusion depth in mm
], SOLID)
self._register_builtin("text_solid_fitted", [
("text", STRING, None), # Text string to render
("max_width", FLOAT, None), # Maximum width in mm (auto-scales height)
("depth", FLOAT, None), # Extrusion depth in mm
], SOLID)
# text_on_surface - Simple way to place text on any surface
# Handles all coordinate frame transformations automatically
self._register_builtin("text_on_surface", [
("text", STRING, None), # Text string to render
("surface_center", POINT3D, None), # Center point of target surface (x, y, z)
("surface_normal", POINT3D, None), # Outward-pointing normal vector
("up_direction", POINT3D, None), # "Up" direction on surface (text baseline to top)
("max_width", FLOAT, None), # Maximum text width in mm
("depth", FLOAT, None), # How far text protrudes from surface
], SOLID)
# Boolean operations (variadic)
self._register_builtin("union", [
("a", SOLID, None),
("b", SOLID, None),
], SOLID, is_variadic=True)
self._register_builtin("difference", [
("a", SOLID, None),
("b", SOLID, None),
], SOLID, is_variadic=True)
self._register_builtin("intersection", [
("a", SOLID, None),
("b", SOLID, None),
], SOLID, is_variadic=True)
self._register_builtin("compound", [
("a", SOLID, None),
("b", SOLID, None),
], SOLID, is_variadic=True)
# List-based boolean aggregation (Phase 3 functional combinators)
self._register_builtin("union_all", [
("solids", make_list_type(SOLID), None),
], SOLID)
self._register_builtin("difference_all", [
("base", SOLID, None),
("tools", make_list_type(SOLID), None),
], SOLID)
self._register_builtin("intersection_all", [
("solids", make_list_type(SOLID), None),
], SOLID)
# Fillet and chamfer operations (OCC-based edge finishing)
self._register_builtin("fillet", [
("s", SOLID, None),
("radius", FLOAT, None),
], SOLID)
self._register_builtin("chamfer", [
("s", SOLID, None),
("distance", FLOAT, None),
], SOLID)
# Pattern operations
self._register_builtin("radial_pattern", [
("shape", UNKNOWN, None), # Any geometry
("count", INT, None),
("axis", VECTOR3D, None),
("center", POINT, None),
], UNKNOWN) # Returns same type as input
self._register_builtin("linear_pattern", [
("shape", UNKNOWN, None),
("count", INT, None),
("spacing", VECTOR, None),
], UNKNOWN)
# Query operations
self._register_builtin("volume", [("s", SOLID, None)], FLOAT)
self._register_builtin("surface_area", [("s", SOLID, None)], FLOAT)
self._register_builtin("area", [("r", REGION2D, None)], FLOAT)
self._register_builtin("perimeter", [("r", REGION2D, None)], FLOAT)
self._register_builtin("centroid", [("s", SOLID, None)], POINT3D)
self._register_builtin("distance", [
("a", POINT, None),
("b", POINT, None),
("tolerance", FLOAT, None),
], FLOAT)
# Transform application - type-specific versions
self._register_builtin("apply", [
("t", TRANSFORM, None),
("shape", SOLID, None),
], SOLID)
self._register_builtin("apply_surface", [
("t", TRANSFORM, None),
("shape", SURFACE, None),
], SURFACE)
self._register_builtin("apply_point", [
("t", TRANSFORM, None),
("p", POINT, None),
], POINT)
self._register_builtin("apply_vector", [
("t", TRANSFORM, None),
("v", VECTOR3D, None),
], VECTOR3D)
# Math functions
self._register_builtin("sin", [("x", FLOAT, None)], FLOAT)
self._register_builtin("cos", [("x", FLOAT, None)], FLOAT)
self._register_builtin("tan", [("x", FLOAT, None)], FLOAT)
self._register_builtin("asin", [("x", FLOAT, None)], FLOAT)
self._register_builtin("acos", [("x", FLOAT, None)], FLOAT)
self._register_builtin("atan", [("x", FLOAT, None)], FLOAT)
self._register_builtin("atan2", [("y", FLOAT, None), ("x", FLOAT, None)], FLOAT)
self._register_builtin("sqrt", [("x", FLOAT, None)], FLOAT)
self._register_builtin("abs", [("x", FLOAT, None)], FLOAT)
self._register_builtin("min", [("a", FLOAT, None), ("b", FLOAT, None)], FLOAT)
self._register_builtin("max", [("a", FLOAT, None), ("b", FLOAT, None)], FLOAT)
self._register_builtin("radians", [("degrees", FLOAT, None)], FLOAT)
self._register_builtin("degrees", [("radians", FLOAT, None)], FLOAT)
self._register_builtin("floor", [("x", FLOAT, None)], INT)
self._register_builtin("ceil", [("x", FLOAT, None)], INT)
self._register_builtin("round", [("x", FLOAT, None)], INT)
self._register_builtin("pow", [("base", FLOAT, None), ("exp", FLOAT, None)], FLOAT)
self._register_builtin("exp", [("x", FLOAT, None)], FLOAT)
self._register_builtin("log", [("x", FLOAT, None)], FLOAT)
self._register_builtin("log10", [("x", FLOAT, None)], FLOAT)
self._register_builtin("pi", [], FLOAT) # Constant: pi
self._register_builtin("tau", [], FLOAT) # Constant: tau (2*pi)
# List operations
self._register_builtin("len", [("list", make_list_type(UNKNOWN), None)], INT)
self._register_builtin("range", [("end", INT, None)], make_list_type(INT), is_variadic=True)
self._register_builtin("concat", [
("list1", make_list_type(UNKNOWN), None),
("list2", make_list_type(UNKNOWN), None),
], make_list_type(UNKNOWN)) # Concatenate two lists
self._register_builtin("reverse", [
("list", make_list_type(UNKNOWN), None),
], make_list_type(UNKNOWN)) # Reverse a list
self._register_builtin("flatten", [
("list", make_list_type(make_list_type(UNKNOWN)), None),
], make_list_type(UNKNOWN)) # Flatten nested list
self._register_builtin("print", [("value", UNKNOWN, None)], BOOL, is_variadic=True)
# Phase 3: Numeric aggregation functions
self._register_builtin("sum", [
("values", make_list_type(FLOAT), None),
], FLOAT) # Sum of numeric list
self._register_builtin("product", [
("values", make_list_type(FLOAT), None),
], FLOAT) # Product of numeric list
self._register_builtin("any_true", [
("values", make_list_type(BOOL), None),
], BOOL) # True if any element is true
self._register_builtin("all_true", [
("values", make_list_type(BOOL), None),
], BOOL) # True if all elements are true
self._register_builtin("min_of", [
("values", make_list_type(FLOAT), None),
], FLOAT) # Minimum value in list
self._register_builtin("max_of", [
("values", make_list_type(FLOAT), None),
], FLOAT) # Maximum value in list
# Utility
self._register_builtin("is_empty", [("s", SOLID, None)], BOOL)
self._register_builtin("empty_solid", [], SOLID)
self._register_builtin("empty_region", [], REGION2D)
def _register_builtin(
self,
name: str,
params: List[Tuple[str, Type, Optional[Any]]],
return_type: Type,
is_variadic: bool = False
) -> None:
"""Register a built-in function signature."""
self._builtins[name] = FunctionSignature(
name=name,
params=params,
return_type=return_type,
is_variadic=is_variadic
)
[docs]
def push_scope(self, name: str = "") -> None:
"""Push a new scope onto the stack."""
new_scope = Scope(parent=self._current_scope, name=name)
self._current_scope = new_scope
[docs]
def pop_scope(self) -> None:
"""Pop the current scope."""
if self._current_scope.parent is not None:
self._current_scope = self._current_scope.parent
[docs]
def define(self, symbol: Symbol) -> bool:
"""
Define a symbol in the current scope.
Returns True if successful, False if already defined in current scope.
"""
if self._current_scope.lookup_local(symbol.name) is not None:
return False
self._current_scope.define(symbol)
return True
[docs]
def lookup(self, name: str) -> Optional[Symbol]:
"""Look up a symbol in the current scope chain."""
return self._current_scope.lookup(name)
[docs]
def lookup_builtin(self, name: str) -> Optional[FunctionSignature]:
"""Look up a built-in function signature."""
return self._builtins.get(name)
[docs]
def is_builtin(self, name: str) -> bool:
"""Check if a name is a built-in function."""
return name in self._builtins
[docs]
def current_scope_name(self) -> str:
"""Get the name of the current scope (for debugging)."""
return self._current_scope.name
[docs]
def get_all_builtins(self) -> Dict[str, FunctionSignature]:
"""Get all registered built-in functions."""
return dict(self._builtins)
# =============================================================================
# Method Signatures for Object Types
# =============================================================================
# Methods available on curve types (Tier 2)
CURVE_METHODS: Dict[str, FunctionSignature] = {
"at": FunctionSignature(
name="at",
params=[("t", FLOAT, None)],
return_type=POINT,
is_method=True
),
"tangent_at": FunctionSignature(
name="tangent_at",
params=[("t", FLOAT, None)],
return_type=VECTOR,
is_method=True
),
"normal_at": FunctionSignature(
name="normal_at",
params=[("t", FLOAT, None)],
return_type=VECTOR,
is_method=True
),
"curvature_at": FunctionSignature(
name="curvature_at",
params=[("t", FLOAT, None)],
return_type=FLOAT,
is_method=True
),
"length": FunctionSignature(
name="length",
params=[],
return_type=FLOAT,
is_method=True
),
}
# Methods available on solid types (Tier 5)
SOLID_METHODS: Dict[str, FunctionSignature] = {
"union": FunctionSignature(
name="union",
params=[("other", SOLID, None)],
return_type=SOLID,
is_method=True
),
"difference": FunctionSignature(
name="difference",
params=[("other", SOLID, None)],
return_type=SOLID,
is_method=True
),
"intersection": FunctionSignature(
name="intersection",
params=[("other", SOLID, None)],
return_type=SOLID,
is_method=True
),
"translate": FunctionSignature(
name="translate",
params=[("v", VECTOR, None)],
return_type=SOLID,
is_method=True
),
"rotate": FunctionSignature(
name="rotate",
params=[("axis", VECTOR3D, None), ("angle", FLOAT, None)],
return_type=SOLID,
is_method=True
),
"scale": FunctionSignature(
name="scale",
params=[("factors", VECTOR, None)],
return_type=SOLID,
is_method=True
),
"apply": FunctionSignature(
name="apply",
params=[("t", TRANSFORM, None)],
return_type=SOLID,
is_method=True
),
}
# Methods available on region2d types (Tier 3)
REGION2D_METHODS: Dict[str, FunctionSignature] = {
"union": FunctionSignature(
name="union",
params=[("other", REGION2D, None)],
return_type=REGION2D,
is_method=True
),
"difference": FunctionSignature(
name="difference",
params=[("other", REGION2D, None)],
return_type=REGION2D,
is_method=True
),
"intersection": FunctionSignature(
name="intersection",
params=[("other", REGION2D, None)],
return_type=REGION2D,
is_method=True
),
}
# Methods available on transform types
TRANSFORM_METHODS: Dict[str, FunctionSignature] = {
"compose": FunctionSignature(
name="compose",
params=[("other", TRANSFORM, None)],
return_type=TRANSFORM,
is_method=True
),
"inverse": FunctionSignature(
name="inverse",
params=[],
return_type=TRANSFORM,
is_method=True
),
"translation": FunctionSignature(
name="translation",
params=[],
return_type=VECTOR3D,
is_method=True
),
"is_rigid": FunctionSignature(
name="is_rigid",
params=[],
return_type=BOOL,
is_method=True
),
}
[docs]
def get_method_signature(obj_type: Type, method_name: str) -> Optional[FunctionSignature]:
"""Get the method signature for a type, if it exists."""
from .types import is_curve, is_solid, is_compound_curve
if is_curve(obj_type):
return CURVE_METHODS.get(method_name)
if is_solid(obj_type):
return SOLID_METHODS.get(method_name)
if is_compound_curve(obj_type) and obj_type.name == "region2d":
return REGION2D_METHODS.get(method_name)
if obj_type.name == "transform":
return TRANSFORM_METHODS.get(method_name)
return None