GeoGebra Scoping System Design
Overview
The ggblab scoping system manages geometric object visibility and accessibility within evolving construction sequences. It integrates with GeoGebra’s layer system and Python’s variable scoping metaphor to provide:
Geometric Scope Trees: Objects grouped by dependency and layer
Visibility Control: Layer-based filtering of accessible objects
Scope-Aware Validation: Ensuring object references are within appropriate scope
Core Concepts
Layer-Based Visibility
GeoGebra’s construction protocol includes layer information (0-9, default 0). Objects on different layers can be:
Hidden/shown independently
Used to organize complexity
Mapped to Python scope levels (global → function → nested)
Dependency-Driven Scoping
The parser’s dependency graph naturally forms a scope tree:
Root objects (global scope)
├─ Point A
├─ Point B
│
├─ Circle(A, B)
│ ├─ Derived: Line segment
│ └─ Derived: Intersection point C
│
└─ Polygon([A, B, C])
└─ Derived: Area calculation
Objects can only reference their ancestors and siblings in this tree.
Implementation Strategy
Phase 1: Passive Tracking (Current)
Track object creation via
command()responsesCache visible objects in
_applet_objectsValidate references against cached set
Phase 2: Layer-Based Scoping (Planned)
Extract layer information from construction protocol
Group objects by layer in the dependency graph
Validate references respect layer visibility
Type System (Future)
GeoGebra’s implicit types should be validated:
# Type hierarchy
GeometricObject:
├─ Point
├─ Line (variants: segment, ray, line)
├─ Circle
├─ Polygon
├─ Conic
└─ ...
# Commands expect specific types
Circle(center: Point, radius: Number | Point) -> Circle
Polygon(points: List[Point]) -> Polygon
Distance(obj1: GeometricObject, obj2: GeometricObject) -> Number
Data Structures
ObjectMetadata
class ObjectMetadata:
name: str # 'A', 'circle1', etc.
type: str # 'point', 'line', 'circle', etc.
layer: int # 0-9 (visibility group)
command: str # Creation command string
dependencies: set # {objects_this_depends_on}
created_at: int # Construction step index
ScopeContext
class ScopeContext:
visible_objects: set # Objects visible in current scope
visible_layers: set # Visible layer numbers
parent_scope: ScopeContext | None
Validation Rules (Progressive)
Current (Phase 1)
✅ Object existence: referenced object is in applet
Planned (Phase 2)
⏳ Layer visibility: object’s layer is visible
⏳ Type compatibility: command argument matches expected type
⏳ Arity checking: correct number of arguments
Future (Phase 3)
⏳ Scope accessibility: object is in accessible scope
⏳ Circularity detection: prevent circular dependencies
⏳ Reachability: ensure all object references are derivable
Integration Points
GeoGebra XML Protocol
Layer information available in
<construction>elementObject metadata in
<element>tags withtypeandlayerattributesCommand strings in
Commandattribute
Parser Integration
ggb_parser.parse()can extract metadataStore metadata in DataFrame alongside protocol
Use for scope-aware subgraph extraction
Validation in command()
async def command(self, c):
if self.check_semantics:
# Existing: object existence
validate_object_existence(c)
# Phase 2: layer visibility
# validate_layer_visibility(c)
# Phase 2: type compatibility
# validate_command_types(c)
await self.comm.send_recv(...)
Error Handling
GeoGebraScopeError (Future)
class GeoGebraScopeError(GeoGebraSemanticsError):
"""Object reference violates scope rules."""
def __init__(self, command, message, out_of_scope_objects=None):
super().__init__(command, message, out_of_scope_objects)
Testing Strategy
Unit tests: Scope tree construction from sample protocols
Integration tests: Command validation in scoped contexts
Edge cases:
Empty construction
Single object (no dependencies)
Circular-like references (e.g., reflected points)
Dynamic layer changes
See Also
validation_strategy.md - Current validation approach
ARCHITECTURE.md - Overall system design
scoping.md - Educational philosophy on scoping