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.
-
Decorator-based Word Registration (
@Word,@DirectWord)- Automatic stack marshalling
- Stack effect notation parsing
- Optional
WordOptionsparameter support - Metadata storage for documentation
-
Module System
DecoratedModulebase 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
Goal: Establish the basic runtime without decorators
- Create
forthic-py/directory structure - Setup modern Python tooling:
pyproject.toml(PEP 517/518)rufffor linting/formattingmypyfor type checkingpytestfor testing
- Use Python 3.10+ features (dataclasses, pattern matching, type hints)
tokenizer.py: Port token types, Tokenizer classliterals.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
Goal: Implement the elegant @Word decorator pattern
decorators/word.py:- Stack effect parser (extract input count, detect WordOptions)
- Metadata storage using weak references
@Worddecorator with automatic stack marshalling@DirectWorddecorator for manual stack access
- Auto-registration of decorated words on
set_interp() getWordDocs()method for introspectiongetModuleMetadata()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
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
- Parse flat array
- Implement array-to-WordOptions conversion
- Test with simple options-accepting words
Deliverable: Options system for flexible word parameters (like [.depth 1] ~> FLATTEN)
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
boolean_module.py:==,<,>,AND,OR,NOT,INmath_module.py:+,-,*,/,ROUND,ABS,MIN,MAXstring_module.py:SPLIT,JOIN,UPPERCASE,LOWERCASE,TRIMrecord_module.py:REC@,<REC,MERGE,KEYS,VALUESjson_module.py:>JSON,JSON>,JSON-PRETTIFY
Deliverable: Full standard library matching TypeScript functionality
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
- Word execution counting
- Timestamp tracking
PROFILE_START,PROFILE_END,PROFILE_DATAPEEK!,STACK!debug words
streamingRun()generator method- Token-by-token execution
- Support for
START_LOG,END_LOG
Deliverable: Complete runtime with all advanced features
Goal: Leverage Python's strengths
- 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 forthicorforthiccommand - 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
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 decoratorclass 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 patternsrc/forthic/interpreter.ts- Core interpreter logicsrc/forthic/module.ts- Module systemsrc/forthic/word_options.ts- Options systemsrc/forthic/modules/array_module.ts- Example module with optionssrc/forthic/modules/core_module.ts- Core operations