Pharo
Pharo is a pure object-oriented programming language and immersive development environment descended from Smalltalk-80, emphasizing simplicity, live coding, and immediate feedback through an integrated IDE that functions like an operating system.[1][2] Developed in 2007 by researchers Stéphane Ducasse and Marcus Denker at Inria Lille - Nord Europe as a fork of the Squeak Smalltalk implementation, Pharo's first open-source release occurred in 2008 to address Squeak's increasingly complex infrastructure.[3] By 2013, a consortium involving over 50 companies had formed to support its development, reflecting growing industrial interest.[3] Key features of Pharo include a concise syntax that fits on a single postcard, with no constructors, static types, or interfaces, enabling everything to be treated as an object; an advanced debugger for on-the-fly code modification and execution restarting; and a live environment supporting rapid prototyping, testing, and deployment.[1] The language is fully open-source under the MIT License, with a vibrant community of over 100 core contributors and thousands participating in its MOOC, which has enrolled more than 8,000 learners.[1][3] As of May 2025, the latest stable version is Pharo 13, introducing enhancements like HDPI support, zoomable UI, and asynchronous I/O via epoll on Unix systems.[4] Pharo has found applications across industries, powering systems in aerospace (e.g., Boeing's ticket management for its Everett plant), defense (Thales' desktop UI tools), finance (CSOB's mobile apps with over 5,000 daily users), and business process automation (ApptiveGrid's SaaS platforms).[5] It is taught in approximately 40 universities worldwide and used by companies like Wyndham Destinations and Lam Research for data integration, reporting, and industrial training.[3][5]Introduction
Overview
Pharo is a pure object-oriented programming language and immersive development environment inspired by Smalltalk, emphasizing live programming, simplicity, and immediate feedback to enable developers to explore and modify code in real time.[1] It promotes an "everything is an object" model, where all entities—from basic data types to control structures—are treated as objects, fostering a uniform and intuitive paradigm for software construction. Pharo's design supports dynamic typing, full introspection and reflection capabilities, allowing programmers to query and alter the system's behavior at runtime, which enhances productivity in exploratory and iterative development.[6] As a cross-platform solution compatible with Windows, macOS, and Linux, Pharo integrates an integrated development environment (IDE), virtual machine runtime, and an OS-like system into a single, cohesive package, providing tools for editing, debugging, testing, and deployment without external dependencies.[1] This all-in-one ecosystem empowers users to build everything from rapid prototypes to sophisticated applications, with a focus on modularity and extensibility. Pharo traces its roots to the Smalltalk-80 programming language, evolving as a modern implementation that prioritizes contemporary software engineering needs.[7] As of 2025, Pharo remains an active open-source project under the MIT license, with Pharo 13.1 serving as the latest stable release from June 2025, continuing to attract developers for its role in agile prototyping, domain-specific languages, and complex system modeling.[8] The community-driven initiative sustains ongoing innovations, ensuring Pharo's relevance in addressing modern challenges like software complexity and developer efficiency.[1]Design Philosophy
Pharo's design philosophy is rooted in pure object-orientation, where every entity—from numbers and classes to control structures—is treated as an object, with no primitives outside this model and all interactions mediated exclusively through message-passing.[9] This uniformity eliminates multi-paradigm complexities, reducing cognitive load by adhering to a simple syntax that fits on a postcard and uses only six reserved words:self, super, nil, true, false, and thisContext.[10] Live coding forms a cornerstone principle, merging the development environment with the running program to enable immediate iteration, real-time feedback, and visual debugging without halting execution.[1] Complementing this is full system malleability, powered by reflection capabilities that allow runtime inspection, modification, and extension of objects, classes, and behaviors, fostering an environment where the system itself is programmable.[11]
The motivations behind Pharo's design stem from addressing limitations in prior Smalltalk implementations like Squeak, particularly the accumulation of legacy code that introduced bloat and impeded modern usability.[10] By systematically removing outdated elements and eschewing external dependencies, Pharo establishes a streamlined, self-contained platform that prioritizes purity and efficiency, reviving Smalltalk's essence for contemporary professional and research applications.[11]
Pharo's goals emphasize enabling exploratory programming through interactive tools that support rapid prototyping and iterative refinement in a live context.[9] It aims to empower the development of domain-specific languages (DSLs) via expressive message-passing and closure mechanisms with non-local returns, while promoting seamless integration of code, data, and user interfaces to create cohesive, persistent applications.[10] A distinctive aspect is its unwavering commitment to message-passing as the sole paradigm, rejecting alternatives to maintain conceptual purity, alongside a focus on "beautiful code" through concise, delegating methods and readable conventions that enhance long-term maintainability.[9]
History
Origins and Fork from Squeak
Pharo originated in March 2008 as a fork of Squeak 3.9, led by Stéphane Ducasse and Marcus Denker at the Software Composition Group (SCG) of the University of Bern in Switzerland. This initiative sought to develop a cleaner, more maintainable evolution of the Smalltalk environment, retaining Squeak's core strengths while addressing longstanding challenges in its codebase. The fork was motivated by Squeak's accumulation of legacy code and unused features over years of broad experimentation, which had resulted in a cluttered system prone to instability.[12][13] Central to the forking decision were Squeak's inconsistent APIs, which complicated maintenance and extension, and its limited focus on contemporary developer tools for professional and research use. The Pharo team aimed to strip the system to essentials—removing cruft, standardizing interfaces, and emphasizing a stable image—to preserve Smalltalk's dynamic power while enabling agile development and live programming. This refactoring effort also addressed Squeak's licensing ambiguities by adopting a fully MIT-licensed core, fostering greater openness and community contribution. Early work prioritized modular design and tool enhancements, such as improved debugging and refactoring support, to create an elegant platform for mission-critical applications.[12][13][14] The initial community coalesced around these cleanup goals, with contributors collaborating via mailing lists and repositories to enhance image stability and remove outdated components like certain graphical frameworks. Significant backing came from INRIA and the RMOD (Reflectivity, Modularity, and Objects for Dynamicity) research team at INRIA Lille - Nord Europe, where Ducasse played a pivotal role in driving technical and organizational progress. This period laid the groundwork for Pharo's distinct identity, culminating in the first public beta release of Pharo 1.0 on July 31, 2009, which introduced a refined baseline for ongoing evolution.[12][13][14]Major Releases and Milestones
Pharo's development progressed through a series of major releases following its fork from Squeak in 2008, with the first stable version, Pharo 1.0, released on April 15, 2010, marking the beginning of focused improvements in stability and usability.[15] Subsequent updates in the 1.x series, including Pharo 1.1 on July 26, 2010, introduced the Cog JIT VM and Settings framework for enhanced performance and configuration management, while versions 1.2 through 1.4 from 2011 to 2012 emphasized UI refinements and overall system stability to support reliable development workflows.[16][17] Pharo 2.0, released in August 2013, integrated Zinc HTTP components, providing a robust framework for HTTP client and server operations that replaced legacy networking code and facilitated web development.[18] This was followed by Pharo 3.0 in April 2014, which incorporated the Spec UI framework to enable declarative construction of composable user interfaces, streamlining tool development.[19] Pharo 4.0, launched in April 2015, added Iceberg for Git integration, allowing seamless version control directly within the environment and marking a shift toward modern collaborative practices.[20] In the mid-period, Pharo 5.0 arrived in 2016 with baseline configuration improvements via Metacello, simplifying dependency management and project bootstrapping for more consistent deployments.[18] Pharo 6.0 in June 2017 enhanced reflective capabilities, including better support for metaclasses and method introspection to empower advanced programming patterns. Pharo 7.0, released in January 2019, introduced full 64-bit support across Linux and macOS platforms alongside a revamped build process using continuous integration for faster iteration cycles.[21] A key milestone during this era was the 2016 adoption of the OpenSmalltalk-VM, which unified VM maintenance efforts across Smalltalk dialects and improved cross-platform compatibility.[22] Recent developments continued the annual release cadence, with Pharo 10.0 on April 5, 2022, delivering better asynchronous I/O support through VM enhancements for efficient non-blocking operations.[23] Pharo 11.0, released May 10, 2023, advanced debugging tools with refined context inspection and step-through capabilities, building on Pharo's renowned interactive debugging heritage.[24] Pharo 12.0 in April 2024 featured reflective API enhancements, including expanded runtime metaobject protocols for deeper system introspection as analyzed in subsequent studies.[25][26] The latest stable release, Pharo 13.1 on June 26, 2025, includes quality-of-life improvements such as updated tools (v0.10.4), Spec (v2.0.3), and Iceberg (v2.4.1), along with bug fixes for robustness and UI handling. Pharo 13.0, released May 21, 2025, introduced new list, table, and tree widgets, enhanced source code navigation, and an updated process browser for better runtime monitoring.[4][8] Throughout its evolution, Pharo's progress has been propelled by community events like the annual ESUG conferences, which serve as key venues for innovation sharing, tool demonstrations, and collaborative planning among developers.[27] These gatherings, held yearly since the early 2010s, have driven advancements in areas from VM optimizations to ecosystem libraries, ensuring Pharo remains a vibrant, forward-looking platform.[28]Relation to Smalltalk
Inheritance from Smalltalk-80
Pharo directly inherits the message-passing model from Smalltalk-80, in which objects communicate exclusively through the sending and receiving of messages, enabling dynamic polymorphism and encapsulation without direct method invocation.[29][30] This model treats all interactions uniformly, as exemplified by expressions like3 + 4, which sends the + message to the object 3 with 4 as the argument.[11] Additionally, Pharo adopts Smalltalk-80's blocks—first-class closures enclosed in square brackets—for deferred execution and procedural abstraction, such as [:x | x + 2] value: 4, which evaluates to 6.[29][31] The metaclass system is preserved intact, ensuring every class is itself an object and an instance of a metaclass, allowing classes to respond to messages and supporting reflective capabilities like SortedCollection class.[11][30] Origins of the Model-View-Controller (MVC) pattern, first formalized in Smalltalk-80 for user interface design, underpin Pharo's graphical frameworks, such as Morphic, where models manage data, views render it, and controllers handle user input.[29][31]
Pharo retains Smalltalk-80's dynamic compilation, permitting runtime evaluation and modification of code through mechanisms like the compile: method, which facilitates live programming and immediate feedback during development.[11][31] Automatic garbage collection, a hallmark of Smalltalk-80's memory management, continues in Pharo to reclaim unused objects without manual intervention, ensuring efficient resource handling in long-running sessions.[29][30] The image-based persistence model is faithfully preserved, where the entire system state—including objects, classes, and methods—is serialized into a single image file for resumption, allowing developers to save and reload a complete, executable environment.[11][31]
Philosophically, Pharo upholds Smalltalk-80's uniform object model, where everything—from primitives to control structures—is an object responding to messages, eliminating special cases and promoting a consistent, extensible paradigm.[29][30] This extends to exploratory programming, supported by inherited tools like workspaces for interactive expression evaluation and browsers for navigating and editing code hierarchies.[11][31] For instance, a workspace can evaluate (Form new extent: 64 @ 64) bitEdit to create and inspect a graphical object on the fly.[31]
Pharo's package system evolves directly from Smalltalk-80's class categories, which organize classes and methods into hierarchical groups for better modularity and maintainability, as seen in categories like Graphics-Primitives.[29][31] While Pharo introduces enhancements for modern use, these foundational mechanisms ensure continuity with Smalltalk-80's interactive and object-centric ethos.[30]
Key Divergences
Pharo diverges from its predecessor Squeak by intentionally removing elements deemed legacy or extraneous to professional software development, thereby streamlining the system for modernity and consistency. Key removals include the EToys multimedia extensions, which were central to Squeak's educational focus but incompatible with Pharo's emphasis on engineering tools; legacy aspects of the Morphic user interface framework, such as outdated visual components and redundant behaviors accumulated over years of Squeak's evolution; and various inconsistent APIs that fragmented the codebase, including remnants of experimental features like MVC (Model-View-Controller) paradigms no longer prioritized. These eliminations reduced the image size and improved maintainability, with EToys specifically excised starting from Pharo 1.0 to eliminate bloat from non-core functionality. Pharo relies on cooperative green threads via the Process scheduler for concurrency and does not support true OS-level multi-threading with shared memory; VM improvements like the Scorch compiler, introduced in Pharo 10, enhance single-threaded performance but not parallelism across multiple cores.[11][32] Over Smalltalk-80, Pharo introduces several enhancements that refine and extend the foundational object-oriented model for contemporary use cases. Traits, a mechanism for composable behaviors allowing fine-grained reuse of methods without inheritance hierarchies, were fully integrated and stabilized in Pharo around 2010, building on earlier Squeak experiments but optimized for Pharo's ecosystem to resolve conflicts explicitly during composition. Slots, introduced in Pharo 4 (2015), represent a major advancement in instance variable management, treating them as first-class objects that enable custom behaviors like lazy initialization, observability, or typing constraints without altering the core language syntax.[33] Additionally, baseline configurations via the Metacello tool provide a declarative way to manage project dependencies and package structures, superseding ad-hoc loading mechanisms in Smalltalk-80 and enabling reproducible builds across environments. These features promote modularity and extensibility while preserving Smalltalk's dynamic nature.[34] Pharo emphasizes a stricter adherence to the "everything is an object" principle than Smalltalk-80, enforcing uniformity by treating primitives like numbers entirely as objects without low-level exceptions or shortcuts in the language semantics, which avoids hybrid procedural elements and ensures all interactions occur via message passing. This purity extends to the removal of any optional static typing hints or annotations present in some Smalltalk-80 derivatives or extensions, recommitting fully to dynamic typing to maintain expressive simplicity and reflective capabilities without compromising the model's elegance. For instance, even basic arithmetic operations on numbers invoke methods on object instances, reinforcing conceptual consistency over performance hacks.[9] In terms of platform integration, Pharo shifts away from Smalltalk-80's deliberate isolation as a self-contained world, incorporating deeper ties to host operating system services for practical deployment. Libraries like OSSubprocess enable seamless spawning and interaction with external OS processes, file systems, and network resources, allowing Pharo applications to interface natively with tools like shell commands or system APIs without encapsulation barriers. Furthermore, the adoption of Git-based version control through the Iceberg tool marks a significant divergence, replacing Smalltalk-80's and early Squeak's Monticello with a modern, distributed system that supports branching, merging, and collaboration via repositories like GitHub, thus aligning Pharo with contemporary development workflows. As of Pharo 13 (May 2025), asynchronous I/O support via epoll on Unix systems further enhances non-blocking operations.[35][34][4]Language Features
Syntax and Semantics
Pharo's syntax is minimalist and uniform, emphasizing message passing as the core mechanism for all computation, where objects communicate exclusively through messages rather than function calls or operators in the traditional sense. Messages fall into three categories: unary messages with no arguments (e.g.,Array new), binary messages with one argument using special symbols like + or - (e.g., 3 + 4 which is equivalent to sending the + message from 3 to 4), and keyword messages with multiple arguments prefixed by keywords ending in colons (e.g., 'hello' copyFrom: 1 to: 3 yielding 'hel'). Binary and unary operators serve as syntactic sugar for these messages, promoting consistency; the language eschews semicolons, braces, or other delimiters common in procedural languages, with statements separated by periods and code blocks enclosed in square brackets [] for readability and structure. Message precedence follows a strict order—parentheses overriding unary, then binary, then keyword messages—evaluated left-to-right within the same precedence level, as in 2 raisedTo: 3 + 1 which computes (2 raisedTo: (3 + 1)) resulting in 16.[36][37]
Semantically, Pharo enforces a purely object-oriented model with dynamic binding, where method resolution occurs at runtime by searching the receiver's class and its superclasses until a match is found, enabling late binding and polymorphism without static type checks. Every value is an object that responds to messages, including primitives like numbers (e.g., 5 timesRepeat: [Transcript show: '*'] prints five asterisks by sending the timesRepeat: message to the integer 5 with a block as argument), underscoring that control flow and operations are message-driven rather than imperative. Boolean semantics treat true and false as objects that selectively execute blocks via messages like ifTrue: or ifFalse:, while nil behaves as the false equivalent by forwarding false-branch messages, as in (x > 0) ifTrue: [positive] ifFalse: [nonPositive]. Blocks [] are first-class closures that encapsulate code for deferred execution, invoked by sending value (or variants like value: arg), supporting functional patterns such as iterations without dedicated loop keywords.[36][37]
Classes in Pharo are defined through subclassing from existing classes, typically starting with Object subclass: #MyClass instanceVariableNames: '' classVariableNames: '' package: 'MyPackage', which instantiates a new class object with an associated metaclass for class-side behavior. Methods are specified by a selector pattern matching the message (e.g., add: aNumber), followed by the implementation body where ^ denotes an explicit non-local return (e.g., double ^ self value * 2), though the last expression serves as an implicit return if omitted, defaulting to self in simple cases. Cascades enable concise chaining of messages to the same receiver using ;, as in OrderedCollection new add: 1; add: 2; add: 3; yourself which builds and returns a collection with three elements. These constructs highlight Pharo's expressive brevity, where instance variables store state privately, accessed only via messages.[36][37]
A distinctive semantic feature is Pharo's full reflection, permitting runtime inspection and modification of code, classes, and execution context—for instance, thisContext [method](/page/Method) retrieves the current method, or Object compile: 'dynamicMethod ^ [42](/page/42)' adds a method on the fly to the Object class. Error handling uses a signal-based system with first-class Exception objects, where exceptions are raised via signal (e.g., ZeroDivide signal), propagating until caught by an on:do: handler (e.g., [1 / 0] on: ZeroDivide do: [:sig | 'Division by zero avoided']), which integrates with the reflective environment to allow seamless debugging and resumption. This approach aligns with Pharo's live, malleable programming paradigm, where semantics prioritize introspection over rigid error propagation.[36][37]
Object-Oriented Paradigms
Pharo embodies a pure object-oriented model where every value in the system is treated as an object, ensuring uniformity and simplicity in design. This approach means that primitives like integers, booleans, and characters are instances of classes such as Number, True, False, and Character, respectively, rather than non-object primitives found in many other languages.[9][38] Pharo employs single inheritance for classes, where each class inherits behavior and structure from a single superclass, forming a linear hierarchy rooted at Object. To enable mixin-like reuse without multiple inheritance, Pharo introduces traits—modular units of behavior that can be composed into classes orthogonally to the inheritance chain. For example, a class definition might includeTrait << #TMyTrait to incorporate the methods from TMyTrait, allowing shared functionality across unrelated classes while resolving conflicts explicitly.[39][40]
Reflection and metaprogramming in Pharo are deeply integrated, providing runtime access to the system's structure and behavior. Metaclasses, such as the metaclass of a class (e.g., Class class), allow classes themselves to be manipulated as objects, enabling introspection and modification of class definitions. Method wrappers facilitate behavioral reflection by wrapping compiled methods to intercept or alter execution, useful for debugging or aspect-oriented programming. The Reflectivity framework, introduced around 2010 and integrated in subsequent Pharo versions, enhances runtime introspection by allowing fine-grained annotations on abstract syntax trees, supporting partial behavioral reflection for tools like object-centric debuggers.[39][41][42]
Advanced features further extend Pharo's object-oriented capabilities. Slots, introduced in Pharo 4, represent instance variables as first-class objects, enabling encapsulation and custom behaviors like lazy initialization or observability without altering the class's layout. Ephemerons provide a mechanism for weak references in finalization scenarios, allowing objects to be notified of garbage collection without preventing it, addressing memory leak issues in weak structures. Fuel, a high-performance serialization framework, supports serializing entire object graphs—including classes and running contexts—to files, facilitating image persistence and migration across environments.[43][24][44]
These paradigms manifest in Pharo's full malleability, where developers can alter class hierarchies at runtime, such as adding or removing subclasses, changing superclasses, or migrating instance variables across existing objects, with the system automatically updating all instances. There are no true global variables; instead, all shared names are stored in the Smalltalk globals dictionary, an instance of SystemDictionary, promoting a uniform object model and avoiding namespace pollution.[9][39]
Implementation Details
Virtual Machine
Pharo's virtual machine (VM) is a cross-platform runtime environment designed to execute Smalltalk-derived bytecode, providing the foundational execution model for the language's dynamic and reflective features. Pharo maintains its own VM, forked from the OpenSmalltalk VM—an open-source implementation that previously supported Squeak, Pharo, Cuis, and Newspeak—and incorporates the Cog just-in-time (JIT) compiler introduced in the mid-2010s to enable efficient compilation of dynamic code during runtime.[45][22][46][47] In August 2025, OpenSmalltalk VM dropped support for Pharo-specific flavors, after which Pharo continues development via its dedicated repository. The Cog JIT extends the traditional interpreter by generating machine code from bytecode, optimizing performance for frequently executed methods while maintaining the VM's portability across platforms like Linux, macOS, and Windows.[48] The VM's architecture centers on a bytecode interpreter that performs stack-based execution, where operations manipulate a runtime stack to evaluate expressions and manage control flow without direct register access, ensuring platform independence. Pharo source code is compiled into platform-neutral bytecode instructions, which the VM interprets or JIT-compiles into native machine code as needed. A key aspect of this architecture is the image format, a binary file that serializes the entire system state—including all objects, methods, classes, and execution contexts—for persistence and quick resumption, allowing developers to save and reload a running environment seamlessly.[49][50][51] Core components of the VM include its memory management system, which employs the Spur generational garbage collector using a mark-sweep-compact algorithm across two generations (young and old) to efficiently reclaim unused objects and minimize pauses. The young generation focuses on short-lived objects via frequent scavenging, while the old generation undergoes less frequent full collections to handle long-lived data. Additionally, the VM provides a foreign function interface (FFI) that enables seamless calls to external C libraries, bridging Pharo's object-oriented model with low-level system resources through type mappings and direct memory access. For concurrency, the VM supports multi-image execution, where multiple independent Pharo images can run simultaneously to achieve parallelism beyond single-image green threads, facilitating distributed or multi-process applications.[52][53][32] The VM's evolution reflects Pharo's maturation as a modern Smalltalk dialect, with a significant transition in Pharo 6 (released in 2017) from the legacy VMMaker build system—used for generating VM code from Smalltalk subsets—to integration with the OpenSmalltalk VM repository, improving maintainability and cross-dialect compatibility. Pharo 7 (2019) introduced 64-bit cleanliness, making the 64-bit VM the recommended configuration for Linux and macOS to leverage larger address spaces and enhanced performance. In Pharo 13 (2025), further refinements to process handling in the VM enhance concurrency primitives, building on prior improvements to support more robust multi-threaded and asynchronous operations within the single-image model.[45][54][4]Performance Optimizations
Pharo's performance is enhanced through targeted optimizations in its Cog virtual machine (VM) and runtime environment, focusing on efficient execution of dynamic code and resource management. The Cog VM employs a just-in-time (JIT) compiler that identifies and compiles "hot" methods—those executed frequently—into native machine code, bypassing interpretation overhead and achieving speeds comparable to statically compiled languages for repetitive tasks. This approach leverages runtime profiling to prioritize compilation, ensuring that only performance-critical paths benefit from the added complexity of code generation.[55] Message dispatch, a core operation in Pharo's object-oriented model, is accelerated via inline caching mechanisms integrated into the Cog VM. These caches store resolved method lookups directly in the calling code, reducing the need for repeated class lookups and enabling polymorphic handling of multiple receiver types without significant slowdowns. For common monomorphic sends, this results in near-direct invocation, while polymorphic cases use multi-slot caches to maintain efficiency. The Spur memory manager, paired with Cog, further supports this by using class indices as cache tags, minimizing indirection costs during garbage collection.[56] Memory management in Pharo prioritizes low-latency interactions through a generational garbage collector in the Spur system, which separates short-lived objects into a young generation for frequent, low-pause scavenging and long-lived ones into an old generation for less frequent collection. This tuning keeps pause times under 500 ms even for heaps around 500 MB, making it suitable for interactive development environments. Incremental collection modes further reduce full GC interruptions, approaching soft real-time behavior by processing work in small increments between bytecode executions.[57] To address object overhead, Pharo introduced slots as first-class representations of instance variables starting in version 5, allowing shared or computed storage that eliminates redundant per-object fields. This optimization reduces memory footprint by up to 30% in data-intensive applications, such as metamodels in the FAMIX framework, by fusing common variables across instances and avoiding pointer bloat in variable classes. Slots maintain full object identity and introspection while enabling the VM to pack objects more densely, improving cache locality and overall allocation efficiency.[58] Since Pharo 10, asynchronous primitives and redesigned foreign function interface (FFI) calls support non-blocking I/O operations, allowing developers to mark potentially blocking external calls as asynchronous for threaded execution. This prevents main-thread stalls during I/O-bound tasks, such as network requests, by leveraging the VM's process scheduler and exception handling to resume computations seamlessly. The approach integrates with Pharo's reflective model without introducing closure overhead, enabling efficient concurrency in server-side applications.[59] Reflection, while powerful in Pharo, incurs runtime overhead from meta-level inspections and modifications; optimizations mitigate this through lightweight proxies and exception-based interception rather than heavy block closures. MethodProxies, for instance, wrap reflective calls with minimal indirection, preserving performance in metaprogramming scenarios like dynamic method addition or behavioral monitoring. These hooks ensure that structural and behavioral reflection remains viable for tools without degrading hot-path execution.[60][61] Pharo 13, released in May 2025, introduces new list, table, and tree widgets built on the Bloc graphics framework, along with other runtime enhancements. These changes contribute to improved system responsiveness in development workflows.[4]Development Environment
Integrated Tools
Pharo's integrated development environment (IDE) is designed for live coding and immersion, allowing developers to interact directly with the running system without compilation cycles. This setup fosters rapid prototyping and exploration, with tools that operate within the image—the in-memory representation of the entire program and environment. Key components include browsers for code navigation, interactive evaluators, debuggers for runtime inspection, and specialized utilities for object examination and system-wide searches, all seamlessly embedded to support continuous development workflows.[62] The core IDE revolves around the Nautilus browser, which serves as the primary interface for navigating and editing code. It features four hierarchical panes displaying packages, classes, protocols (method categories), and methods, with a bottom pane for source code viewing and modification. Developers can right-click in any pane to access contextual menus for operations like browsing hierarchies or implementing methods, enabling efficient organization of the class library stored directly in the image. Complementing this, the Playground provides a simple window for typing and executing Pharo expressions interactively using "Do it" commands, ideal for quick experiments, prototyping, or testing snippets without full class definitions. The Debugger, invoked by failing tests, keyboard shortcuts like CMD-., or explicit halts, offers step-through execution, stack inspection, and unique hot-swapping capabilities, where code can be edited and applied mid-execution to alter program behavior on the fly.[63][62] Version control is handled natively through Iceberg, a Git integration tool introduced in Pharo 6.0 and refined in subsequent releases to manage large-scale projects like Pharo itself, which spans over 600 packages. Iceberg synchronizes the live image with Git repositories, supporting cloning, committing, branching, merging, and remote operations via SSH or HTTPS directly within the environment. Developers use the Repositories browser to oversee projects and the Working Copy browser to handle branches—such as creating a new one from an issue—and perform merges, with visual conflict resolution embedded in the image to maintain workflow continuity without external tools.[34] Testing and refactoring are supported by the built-in SUnit framework, originally by Kent Beck, which enables unit, integration, and functional tests through simple subclasses ofTestCase. Tests are written as methods prefixed with "test," using assertions like assert:equals: for value comparisons or should:raise: for exception verification, executed via the Test Runner for pass/fail/error feedback (green/yellow/red indicators). Nautilus integrates refactoring directly, offering actions like renaming classes or methods and extracting methods from selected code via right-click menus, streamlining code evolution while preserving system integrity.[63]
Unique tools enhance exploration and productivity: the Inspector allows deep dives into object structures, revealing instance variables, methods, and contents through expandable views for runtime analysis. Spotter, an omnibox-style search utility, enables fuzzy querying of methods, classes, pragmas, or even code examples, surfacing results incrementally for quick navigation across the system. Pharo 13 addresses prior limitations in source handling with enhanced text navigation and editing for precise code manipulation, alongside a new Process Browser for monitoring and managing running processes, improving oversight in complex, live environments.[62][4]