Forthic Python Runtime Implementation Plan
Create a modern Python runtime for Forthic that mirrors the TypeScript implementation, with special focus on the elegant Word decorator pattern for easy module creation.
Key TypeScript Patterns to Mirror:
-
Decorator-based Word Registration (@Word, @DirectWord)
- Automatic stack marshalling
- Stack effect notation parsing
- Optional WordOptions parameter support
- Metadata storage for documentation
-
Module System
- DecoratedModule base class with automatic word registration
- Module metadata with categories, examples, options info
- Import/export with prefixing support
-
Core Components
- Interpreter with stack management
- Tokenizer for parsing Forthic syntax
- Module registry and module stack
- Literal handlers (dates, numbers, booleans)
- WordOptions for flexible parameter passing
Phased Implementation Plan
Phase 1: Core Infrastructure (Foundation)
Goal: Establish the basic runtime without decorators
- Create forthic-py/ directory structure
- Setup modern Python tooling:
- pyproject.toml (PEP 517/518)
- ruff for linting/formatting
- mypy for type checking
- pytest for testing
- Use Python 3.10+ features (dataclasses, pattern matching, type hints)
1.2 Basic Types & Tokenizer
- tokenizer.py: Port token types, Tokenizer class
- literals.py: Basic literal handlers (int, float, bool, string)
- Create Token, CodeLocation, PositionedString classes
- module.py:
- Word base class
- PushValueWord, DefinitionWord, ExecuteWord
- Variable class
- Module class (without decorators)
- Stack class with proper typing
- interpreter.py:
- Stack operations
- Module stack management
- Token handling
- Word execution
- Error handling classes
Deliverable: Basic interpreter that can execute simple Forthic code with manually registered words
Phase 2: Decorator System (The Magic)
Goal: Implement the elegant @Word decorator pattern
2.1 Decorator Infrastructure
- decorators/word.py:
- Stack effect parser (extract input count, detect WordOptions)
- Metadata storage using weak references
- @Word decorator with automatic stack marshalling
- @DirectWord decorator for manual stack access
2.2 DecoratedModule Base Class
- Auto-registration of decorated words on set_interp()
- getWordDocs() method for introspection
- getModuleMetadata() for module-level docs
- registerModuleDoc() helper
- Markdown doc string parser (Categories, Options, Examples)
- Support for categorized word lists
Deliverable: Decorator system allowing natural Python method definitions to become Forthic words
Phase 3: WordOptions System
Goal: Enable flexible optional parameters
- word_options.py:
- Parse flat array [.key1 val1 .key2 val2] into dict
- get(), has(), toDict() methods
- Integration with @Word decorator
3.2 Core Module ~> Operator
- Implement array-to-WordOptions conversion
- Test with simple options-accepting words
Deliverable: Options system for flexible word parameters (like [.depth 1] ~> FLATTEN)
Phase 4: Standard Library Modules
Goal: Port essential modules using decorators
- Stack operations: POP, DUP, SWAP
- Variables: !, @, !@, VARIABLES
- Module system: EXPORT, USE_MODULES
- Control flow: IDENTITY, NOP, DEFAULT, *DEFAULT
- String interpolation: INTERPOLATE, PRINT
- Transform: MAP, SELECT, REDUCE, FOREACH
- Access: NTH, LAST, SLICE, TAKE, DROP
- Combine: APPEND, ZIP, CONCAT
- Group: GROUP_BY, GROUP_BY_FIELD, BY_FIELD
- Options support: with_key, push_error, depth, push_rest
4.3 Other Standard Modules
- boolean_module.py: ==, <, >, AND, OR, NOT, IN
- math_module.py: +, -, *, /, ROUND, ABS, MIN, MAX
- string_module.py: SPLIT, JOIN, UPPERCASE, LOWERCASE, TRIM
- record_module.py: REC@, <REC, MERGE, KEYS, VALUES
- json_module.py: >JSON, JSON>, JSON-PRETTIFY
Deliverable: Full standard library matching TypeScript functionality
Phase 5: Advanced Features
Goal: Complete feature parity
- Use zoneinfo (Python 3.9+) for timezone handling
- Implement temporal literal handlers
- DateTime module: >DATE, >DATETIME, ADD_DAYS, FORMAT, SUBTRACT_DAYS
5.2 Profiling & Debugging
- Word execution counting
- Timestamp tracking
- PROFILE_START, PROFILE_END, PROFILE_DATA
- PEEK!, STACK! debug words
- streamingRun() generator method
- Token-by-token execution
- Support for START_LOG, END_LOG
Deliverable: Complete runtime with all advanced features
Phase 6: Python-Specific Enhancements
Goal: Leverage Python's strengths
6.1 Pythonic Conveniences
- Context managers for module scope
- Async/await support (already in TS version)
- Generator-based iteration
- Type hints throughout
- Easy integration with pandas DataFrames
- NumPy array support
- Requests/httpx for HTTP operations
- SQLAlchemy integration helpers
- PyPI package as forthic
- CLI tool: python -m forthic or forthic command
- REPL with readline support
- Documentation site (Sphinx or MkDocs)
Deliverable: Production-ready Python package
- Type Hints: Full typing with typing, Protocol, TypeAlias
- Dataclasses: For Token, CodeLocation, etc.
- Pattern Matching: For token handling (Python 3.10+)
- Async/Await: Support async words naturally
- Descriptors: For elegant decorator implementation
Decorator Implementation Strategy:
from typing import Any, Callable
from functools import wraps
def Word(stack_effect: str, description: str = "", name: str = None):
"""Decorator that auto-marshalls stack arguments"""
def decorator(method: Callable) -> Callable:
# Parse stack_effect to get input_count and has_options
parsed = parse_stack_notation(stack_effect)
# Store metadata
store_word_metadata(method, {
'stack_effect': stack_effect,
'description': description,
'word_name': name or method.__name__.upper(),
'input_count': parsed.input_count,
'has_options': parsed.has_options
})
@wraps(method)
async def wrapper(self, interp: Interpreter):
# Pop inputs from stack
inputs = []
for _ in range(parsed.input_count):
inputs.insert(0, interp.stack_pop())
# Check for optional WordOptions
options = {}
if parsed.has_options:
top = interp.stack_peek()
if isinstance(top, WordOptions):
opts = interp.stack_pop()
options = opts.to_dict()
inputs.append(options)
# Call original method
result = await method(self, *inputs)
# Push result if not None
if result is not None:
interp.stack_push(result)
return wrapper
return decorator
class ArrayModule(DecoratedModule):
"""Array and collection operations"""
def __init__(self):
super().__init__("array")
@Word("( array:list item:any -- array:list )", "Append item to array")
async def APPEND(self, array: list, item: Any) -> list:
result = array or []
result.append(item)
return result
@Word("( items:list forthic:str [options:WordOptions] -- mapped:list )",
"Map function over items")
async def MAP(self, items: list, forthic: str, options: dict) -> list:
with_key = options.get('with_key', False)
result = []
for i, item in enumerate(items):
if with_key:
self.interp.stack_push(i)
self.interp.stack_push(item)
await self.interp.run(forthic)
result.append(self.interp.stack_pop())
return result
- Unit tests for each component (pytest)
- Port all TypeScript tests to Python
- Property-based testing with Hypothesis
- Integration tests for full workflows
- Performance benchmarking vs TypeScript runtime
- Docstrings following NumPy/Google style
- Auto-generated API docs (Sphinx)
- Tutorial notebooks (Jupyter)
- Examples directory matching TypeScript version
- All TypeScript tests pass in Python
- Decorator pattern is elegant and Pythonic
- Performance within 2x of TypeScript (acceptable for initial version)
- Full type coverage (mypy strict mode)
- Package installable via pip
- Documentation at docs.forthic.org/python
- Phase 1: 1 week (Core Infrastructure)
- Phase 2: 3-4 days (Decorator System - critical phase)
- Phase 3: 2 days (WordOptions System)
- Phase 4: 1 week (Standard Library Modules)
- Phase 5: 3-4 days (Advanced Features)
- Phase 6: 1 week (Python-Specific Enhancements)
Total: ~4 weeks for complete implementation
The TypeScript runtime at ../forthic-ts/ serves as the reference implementation. Key files to study:
- src/forthic/decorators/word.ts - Decorator pattern
- src/forthic/interpreter.ts - Core interpreter logic
- src/forthic/module.ts - Module system
- src/forthic/word_options.ts - Options system
- src/forthic/modules/array_module.ts - Example module with options
- src/forthic/modules/core_module.ts - Core operations