This section provides in-depth perspectives and the design rationale behind Clprolf. It is not intended as a quick introduction to the language, but rather as a comprehensive and reflective guide for those who want to understand Clprolf deeply — both in its structure and its philosophy.
While primarily written for readers already familiar with Clprolf, this chapter can also serve as a learning document for those who wish to explore the language in a more profound way — discovering not only how it works, but why it was designed that way.
It reveals the principles, intentions, and conceptual architecture that make Clprolf unique: a language that was built to make clarity and coherence the natural outcome of programming.
CLear PROgramming Language and Framework (Clprolf)
Clprolf is a niche programming language designed to help build systems with a mindful and coherent structure. It provides a clear framework for creating software with consistency, purpose, and long-term stability.
Clprolf is a specialized, guided language. It defines predefined components and enforces strict rules for inheritance and interfaces, with a strong focus on algorithmic programming.
It is particularly suited for:
Clprolf can also serve as a tool for memory and comprehension. It works much like a mnemonic or memory palace, helping developers who struggle to retain large, abstract architectures.
It is also a medium for testing, explaining, and validating scientific theories, by means of simulation, algorithm description, and clear actor modeling.
This document presents both:
Clprolf is deliberately minimalistic to simplify development. It is a powerful teaching tool, but not limited to educational contexts.
Programming in Clprolf focuses on functional problems and on describing the interactions of actors. For technical concerns, it specifies what a worker must do, not how the work is carried out internally.
Clprolf is designed for clarity, simplicity, and ease of use. It naturally embeds object-oriented principles and significant design patterns — a rare feature for a programming language.
It supports both:
🧠 One of the main — perhaps the most important — goals of Clprolf is to make writing programs easier.
Programming is the weaving together of design and algorithmic concerns. Clprolf was built to support both.
A dedicated GitHub repository has been created for Clprolf. The project is open source and distributed under the MIT license.
Clprolf was not created to enforce design principles, but to make good design emerge by itself. It works the same way Bison builds parsers without requiring you to think about grammar theory — Clprolf helps you design without realizing you are doing so.
Traditional principles such as the Single Responsibility Principle (SRP) or the SOLID guidelines describe what a good design should look like, but not how to achieve it. They are abstract goals — useful, but mostly negative in nature: they tell you what not to do, without showing how to design meaningfully.
Clprolf brings the how directly into the language.
By simply choosing a role — agent, worker_agent, model, or information — you already make a design decision.
Each role carries a unique nature, and that nature defines what the class truly is.
In Clprolf, a responsibility finally becomes something tangible: it’s a nature. A class has one nature — therefore, one responsibility. There’s no need to debate what “responsibility” means; the language gives it a concrete identity.
But Clprolf goes further than just recommending a single responsibility. It guides you toward a design that makes sense — a design that is coherent, memorable, and controllable. Instead of producing abstract compliance, Clprolf produces meaningful architecture.
Whereas classical principles restrict you by saying what must not be done, Clprolf expands your freedom by making structure visible and intuitive. It is not a dictatorial language enforcing rules; it simply makes incoherent design structurally impossible.
That’s why the SRP becomes a consequence, not a rule. A well-formed Clprolf program naturally respects it, because the act of choosing a nature already fixes the class’s scope and purpose.
Clprolf, therefore, is a designer of design — a language that doesn’t apply methodology, but turns clear thought into structure. It’s not about following design rules — it’s about designing so clearly that the rules follow you.
With Clprolf, you obtain a system that remains fully masterable. The mechanics of the objects are intuitive, and there is a natural separation between business logic and technical code.
Semantic rules allow the compiler to verify that the architecture stays coherent and logical over time. They prevent the drift into uncontrolled systems — those where relationships between objects, or the objects themselves, become too complex to reason about.
Clprolf acts as a safeguard against the illusion of total freedom — the belief that “anything is possible” is often what produces systems that are unmaintainable and chaotic.
Clprolf does not remove creativity. It simply ensures that freedom remains structured, and that every decision stays connected to meaning.
Most existing object-oriented languages are neutral: they provide mechanisms such as classes, objects, and inheritance, but they do not indicate how objects should be designed or coded. As a result, programmers rely on external guidelines, principles, or patterns.
Clprolf is different. It is not only a language, but also a methodology — designed to make object-oriented programming as effective as possible. It embeds a set of practical guidelines directly into its structure.
Give meaning to classes Every class should have a clear and unique responsibility.
Use inheritance rigorously Inheritance must remain coherent and should never be driven by technical convenience.
Separate layers Clearly distinguish simulation or business logic from technical layers such as DAOs, persistence, or infrastructure code.
Interfaces for versions Interfaces are primarily intended to provide alternative implementations (versions). Capacity interfaces are the exception: they express shared functionality across versions.
Interface inheritance The inheritance of interfaces should mirror the hierarchy of their corresponding classes, ensuring consistency.
Favor composition over inheritance When possible, prefer composition to deep hierarchies, improving flexibility and maintainability.
This methodology is fully compatible with:
It reflects both practical experience in object-oriented programming and the synthesis of widely accepted principles, offering a rigorous yet intuitive approach to building robust systems.
However, if you already follow your own methodology, or if you master programming well with existing principles and patterns, you may not need Clprolf.
Applying methodology becomes far easier when it is built into the language. Principles like SOLID or design patterns are valuable, but hard to constantly keep in mind while coding.
Clprolf changes the way you approach design: you build agents, worker agents, and other specialized components, rather than starting from generic objects. The same applies to interfaces — they are defined as versions, capacities, or agent-specific variants.
Yet under the hood, everything remains pure object-oriented programming: agents are still objects, and all interfaces are standard OOP interfaces.
Clprolf is first and foremost a language for classes and interfaces, with a strong emphasis on algorithmic coding — particularly in the areas of concurrency and parallelism. Its features for interface inheritance and its semantic checks on class and interface declensions make it a full-fledged language in its own right.
Clprolf is a Java-compatible language.
It redefines some Java keywords such as class, interface, extends, and implements,
and introduces new ones like with_compat, nature, and underst.
All Java libraries can be used directly in Clprolf. You can also write Java code inside Clprolf source files, except for the few replaced keywords.
Clprolf classes replace Java classes, so all standard Java modifiers can still be used with them — for example:
public worker_agent Launcher { }
The same applies to interfaces.
Clprolf follows the Open/Closed Principle, not by modifying Java, but by adding clear notions of role and structure on top of existing object-oriented concepts.
The current Clprolf compiler uses Java 8 as its host language. Java serves as a stable and portable support, while Clprolf brings its own semantic layer and conceptual clarity on top of it.
The Clprolf language can be seen as a Java clone with specific changes and additions.
For an experienced Java programmer, becoming proficient in Clprolf may take several weeks on average. The language remains close to Java, and its concepts are relatively easy to grasp for developers already accustomed to abstraction and design. Moreover, the limited number of new keywords helps ease the learning process.
This makes the transition smoother than learning a completely new paradigm.
class keyword disappears.Clprolf provides method modifiers to add additional semantic controls on functions, extending beyond standard Java capabilities.
extends keyword is replaced by nature, which requires the programmer to explicitly declare the nature of the parent.with_compat when referenced in variables, arguments, or attributes.Interfaces serve only as contracts, and must be created as either:
These changes differentiate Clprolf from Java:
with_compat.Together, these features provide a clearer, more structured, and role-driven approach to programming.
The early idea behind object-oriented programming came from biological cells — small autonomous entities that communicate through messages. Over time, this living vision faded, replaced by mechanical notions of classes and inheritance.
In Clprolf, the idea is reborn in a clearer form.
Each agent or worker_agent behaves like a cell, with its own nature and purpose.
Their relations and communications are explicitly designed by the programmer,
so that interaction becomes part of the model itself, not a side-effect of code.
Together, these cells form a coherent organism — a system where roles, flows, and responsibilities maintain balance and meaning. Clprolf does not imitate biology; it shares its logic: clarity through Autonomy, life through interaction.
In Clprolf, classes are naturally organized into layers that align with the principles of the three-tier architecture.
The top layer is composed of:
agent classes (synonyms: abstraction, simu_real_obj),model classes.This is where we find the business logic of the application, but not exclusively. Every agent, representing a real-world abstraction, is considered business-level code.
The second layer is composed of technical classes, where the computer is seen as a worker abstraction.
These are the worker_agent classes (synonyms: comp_as_worker).
This layer typically corresponds to the Data Access Layer (DAL) and Presentation Layer in a traditional three-tier architecture.
In Clprolf, we make a clear separation:
Anything that is not part of an agent’s role must be placed in a worker agent.
Some types of software — such as parts of an operating system — are composed almost entirely of the technical layer. In these cases, the worker agent layer may directly invoke elements of the agent layer.
In Clprolf, we strive to capture some of the richness of natural languages. Every object has a declension (also called its role or class responsibility), which defines its function within the system. Declensions are central to the design philosophy of Clprolf.
Each declension may also have synonyms, which are fully equivalent. Developers may choose one synonym over another depending on their perspective or the emphasis they want to convey.
Every class in Clprolf must take on one of a small set of predefined responsibilities:
worker_agent (also comp_as_worker)agent (also abstraction, simu_real_obj)modelinformationindef_obj (indefinite object)These five declensions represent the core object roles in Clprolf. Some of them have synonyms, which emphasize different aspects but are fully equivalent.
agent
Main role for classes that simulate real-world entities.
Example: an Animal with methods like eat() or run().
Synonyms: abstraction, simu_real_obj.
These older names are still available, but agent is the preferred keyword.
worker_agent (or comp_as_worker)
Declares a class that delegates technical work to the computer, seen as a worker executing algorithms.
The worker manages its own resources (memory, processor, peripherals) and runs algorithms in compiled form.
model
Declares a class that models real-world data without behavior.
Example: a Customer class with only attributes.
This is typically used for entities.
information
Data-only class, typically used by workers as internal structures.
It should not be mixed with real-world simulations, except in technical edge cases.
indef_obj
Indefinite object, used when no specific role is desired.
Equivalent to a traditional OO class without an explicit responsibility.
Clprolf is built on the observation that some objects in a system represent agents — abstractions of real-world entities — while others act as workers, carrying out technical or computational tasks.
This separation helps clarify design choices, maintain clean responsibilities, and make object-oriented programming easier to reason about.
Agents and Workers Every agent can also act as a worker, since computers execute agents as specialized workers. However, the number of explicit workers in a system should be minimized for clarity and efficiency.
Models and Information
Every model can also be represented as information, since computers store models as data.
Still, it is important to avoid misusing information where a model would be more appropriate.
Unidirectional Substitutions Substitutions are not symmetric:
Clprolf introduces a few small but important differences in how class inheritance is expressed, compared to Java.
nature instead of extends
In Clprolf, inheritance expresses that a class is of the same nature as another.
For example, a car is of the same nature as a vehicle in the real world.
The keyword nature is reserved for classes only — it has no meaning for interfaces.
Even worker agents have a defined role for their job; they must use nature when inheriting from another class.
contracts instead of implements
The contracts keyword lists the interfaces that a class respects — they are seen as contracts, not as mere technical implementations.
Clprolf deliberately avoids with_compat in class declarations, since with_compat emphasizes that an object (not a class) is compatible.
The traditional Java keyword implements focuses on the mechanical aspect of implementation, while contracts reflects the philosophy of respect and agreement.
class_for ModifierIn pure Clprolf, there is an optional modifier class_for that can be used instead of class.
It appears before the role keyword, explicitly tying the class to its declension.
This construct is not available in the Clprolf frameworks, since the standard class keyword already exists there.
Examples:
public class_for agent Car { ... }
public class_for worker_agent Launcher { ... }
To remain compatible and powerful, Clprolf accepts all standard Java modifiers in class and interface declarations. This includes access modifiers and other familiar constructs, which can be used in exactly the same way.
Each declension keeps only a minimal set of synonyms, and every synonym reflects a specific aspect:
agent (agent aspect), abstraction (object aspect), simu_real_obj (simulation aspect)worker_agent (agent aspect), comp_as_worker (simulation aspect)modelinformationindef_objThis structure makes the system both easy to memorize and easy to teach. Synonyms are no longer arbitrary alternatives but clearly justified by the perspective they express.
worker_agentIn Clprolf, the general recommendation is to avoid overusing worker_agent. Real-world simulations (agent) are usually more intuitive and less technical.
For example, although interpretations are flexible, it is often more natural to see a Sort class as an agent rather than a worker_agent.
The main recommended use cases for worker_agent are:
worker_agent.AnimalRealiz worker_agent that contains the computational code and tools to render and manage the interactive behavior of an Animal agent.Even in system programming, however, worker_agent classes often collaborate with agent classes (e.g., for graphical interfaces, memory handling, connections, threads). The rule of thumb is simple: it is the computer who does the job.
agent ↔ worker_agent relationship+-----------------+          +----------------------+
|     Agent       |          |     Worker_agent     |
|  (simulation)   |          |   (realization)      |
+-----------------+          +----------------------+
|  Animal         |  <---->  |  AnimalRealiz        |
|  eat(), move()  |          |  render(), input()   |
+-----------------+          +----------------------+
Here, Animal is an agent that simulates the real-world entity.
AnimalRealiz is its worker_agent counterpart, responsible for computational tasks such as display and input.
In Clprolf, the qualifiers agent, abstraction, and simu_real_obj are equivalent.
They all designate the same declension, but with slightly different emphases.
abstraction highlights the idea of a black box that hides details while providing functionality.
For example, a coffee machine is an abstraction, even outside computer science.
In Clprolf, abstractions are always abstractions of something in the real world.
simu_real_obj emphasizes the idea of a simulation object, emulating a real-world entity.
The notion of “real-world object” is broad and may include abstract concepts, such as a socket or a connection.
Here, the real-world object is understood as a concept.
Use abstraction when representing abstract ideas or system abstractions (e.g., a Connection class).
These abstractions are typically consumed by worker_agent classes.
Use simu_real_obj when representing more concrete real-world entities (e.g., a Vehicle class).
There is no strict rule — it is a matter of developer preference and sensibility. Both terms are fully valid and interchangeable.
The worker_agent declension is not only about separating agent code from pure computer tasks — it is about treating the computer as a worker. The “simu” prefix highlights this metaphor: as if the computer were a real-world worker. Its job is to manage peripherals, handle resources, and perform tasks that are inherently technical.
The idea is algorithmic: an algorithm is executed for a worker, and here the worker happens to be a computer. In principle, a human could also play the role of a worker — the distinction lies only in the nature of the task. This perspective connects to ALGOL 60’s vision of algorithms: abstracting the worker, and seeing the computer as an executor in human-like terms.
By assigning technical tasks to worker_agent classes, Clprolf reduces the impact of technical code. It is “just work” performed by a worker. The rule of thumb becomes simple: who is doing the job?
agent, the job belongs to the simulated entity (e.g., an animal calls eat()).worker_agent, the job belongs to the computer (e.g., a launcher class running an algorithm).Thus, worker_agent provides a clean simulation of the computer as a worker, just as agent provides simulations of real-world entities.
A worker_agent can use system abstractions (File, Connection, etc.). Only workers are allowed to use such abstractions, preserving the “third-person” perspective of simulation. Compiler checks enforce this restriction. The only exception is factories of system abstractions (e.g. a connection factory): factories instantiate objects but do not use them, so they can be modeled as abstraction classes.
For practical reasons, an agent may occasionally need to include small amounts of technical code. In such cases, the @Forced_pract_code annotation makes this explicit.
Finally, some design patterns reinforce this distinction: for example, the View and the Model of MVC cannot be modeled as agent classes in Clprolf, since they rely on system abstractions — and therefore belong under worker_agent.
System abstractions such as File or Connection should generally appear only in worker_agent classes.
Exceptions may be made for practical reasons or for thread-like abstractions.
This rule follows naturally from the third-person perspective:
simu_real_obj).indef_objFor situations where a role is not desirable or not yet determined, Clprolf provides the indef_obj (indefinite object) declension.
It behaves like a traditional OOP object and keeps the system flexible.
indef_obj (or @Indef_obj in the framework).In summary
By integrating declensions, genders, and advices, Clprolf ensures clear design choices, unambiguous roles, and a coherent semantic structure for all entities — both classes and interfaces.
These three notions — declension, gender, and advice — form the semantic backbone of Clprolf. They define what a class represents, how it behaves, and for whom it was designed.
In Clprolf, genders are optional markers that refine the interpretation of an agent declension. They do not change the role of the object — it remains an agent — but they express a particular attitude or posture of that agent within the system.
A gender gives nuance to how the agent acts or is perceived: whether it behaves like a human expert, a technical component, or a static utility. It adds semantic precision without altering the structure.
Genders make the intent of a class clearer while preserving the same declension and architectural consistency. They are optional, never enforced, and serve only to enrich the meaning of design.
@Human_expert, but with a more technical interpretation — the class is an “expert component” specialized in its task.Note: Genders are available only for the agent declension, except
@Static, which may also apply to the worker_agent declension.
💡 Genders refine meaning; they describe the spirit of a class, not its structure or responsibility.
@Human_expert   // or @Expert_component
public agent MeteoExpert { /* (...) */ }
@Expert_component ↔ @Human_expert These genders overlap strongly. A human expert can also be viewed as a component.
@Human_expert
public agent NetworkTalker { /* (...) */ }
is equivalent to:
@Expert_component
public agent NetworkTalker { /* (...) */ }
In the Java framework, genders are available for agent-like roles through an optional gender attribute.
For example:
@Agent(gender = Gender.EXPERT_COMPONENT)
public class Controller { /* (...) */ }
The available genders are:
Gender.HUMAN_EXPERT, Gender.EXPERT_COMPONENT, Gender.STATIC, Gender.HUMAN_EXPERT_STATIC, Gender.EXPERT_COMPONENT_STATIC.
In Clprolf, interfaces are organized into three categories. Collectively, they are called compatibility interfaces.
compat_interf_version:
Used when a class provides a concrete implementation — a version.
This is typically the case when offering different implementations of the same DAO (e.g., database, web services, in-memory).
When interfaces are used for loose coupling, they should be declared as compat_interf_version to indicate that the design anticipates alternative implementations instead of binding to a specific class.
Features for interface inheritance allow a class role to be attached to version interfaces, further simplifying loose coupling.
compat_interf_capacity:
Ensures a common functionality across multiple compat_interf_version interfaces.
A capacity interface always targets either an agent-like or a worker-like version interface.
compat_interf:
A fallback case for when no role is assigned to an interface, in order to remain flexible.
Its use is not recommended. 
compat_interf (or @Compat_interf in the framework).This makes it possible to use traditional Java interfaces (or equivalents in other host languages), when desired.
Outside of these scenarios, interfaces are not used in Clprolf. However, the features for interface inheritance allow roles to be attached to version interfaces, making it possible to treat them with a true inheritance perspective (using nature, even in multiple inheritance cases).
Interfaces also have declensions, with possible synonyms:
compat_interf_version declension = version_inhcompat_interf_capacity declension = capacity_inhcompat_interf declension — no synonymDeclensions can be applied to an interface to indicate which class declensions are allowed to implement it (via contracts).
with_compat ModifierA key difference in Clprolf is that every use of an interface must be preceded by the keyword with_compat (with compatibility).
Example:
void drink(with_compat Drink drinkable) { ... }
with_compat is a modifier applied in variable declarations (local variables, attributes, or method parameters). Its purpose is to make explicit that the reference is not tied to a particular class, but to an interface compatibility.
Typical usages include local variables and method arguments.
There is no with_compat indication for a method’s return type. This is the exception to the rule, because the return type is not a variable declaration. In practice:
with_compat is valid for all Clprolf interface types: version, capacity, or generic compatibility.
This allows capacity interfaces to be used directly in variables, even though a class cannot directly inherit from them.
Capacity interfaces are only meant to extend compat_interf_version interfaces. They express functionality that is common across different families of version interfaces, and thus across the classes that implement them. Think of versions as alternatives, and capacities as common traits shared across those alternatives.
A capacity interface can never be implemented directly by a class. This restriction avoids confusion with version interfaces — otherwise, something like a Connection might mistakenly be treated as a capacity. By keeping capacities at the interface level (interfaces of interfaces), Clprolf prevents unnecessary multiple inheritance on classes and keeps the design clear.
Capacity interfaces can have a gender called an Advice, which specifies their target role:
@Agent_like_advice advice@Worker_like_advice adviceThis advice, works like a sub-role. It indicates whether the capacity applies to agent-like roles or to worker-like roles. When a version interface implements a capacity, it must declare a class role, and the compiler will check that this role is consistent with the advice.
⚠️ If no advice is explicitly given, the default is agent-like.
In pure Clprolf, the advice is given by an annotation above the interface:
@Agent_like_advice@Worker_like_adviceIn the Clprolf Framework, advice is expressed as a sub-role of the @Compat_interf_capacity annotation:
@Compat_interf_capacity(Advice.FOR_AGENT_LIKE)@Compat_interf_capacity(Advice.FOR_WORKER_LIKE)The advice is always mandatory (or assumed agent-like by default), because Clprolf deliberately prevents ambiguous situations — for example, a with_compat clause that could accept both agent-like and worker-like objects.
Example in the Language:
// This interface can be extended only by a compat_interf_version with an agent-like role(abstraction, agent, simu_real_obj)
@Agent_like_advice
public compat_interf_capacity Eatable {
    void eat(int quantity);
}
//We have to give the class role, because it has a capacity
public version_inh agent Animal extends Eatable {
    int getAge();
    String getName();
    void setAge(int age);
    void setName(String name);
    void run();
}
//We have to give the class role, because it has a capacity
public version_inh agent Person extends Eatable {
    void laugh();
}
//We can not write Eatable in the contracts, because it is a capacity.
public agent AnimalClass contracts Animal {
    //(…)
    public int getAge(){ //(…) }
    public String getName(){ //(…) }
    public void setAge(int age){ //(…) }
    public void setName(String name){ //(…) }
    public void run(){
        System.out.println("I am running");
    }
    //Eatable
    public void eat(){
        System.out.println("I am eating");
    }
    //
}
//We can not write Eatable in the contracts, because it is a capacity.
public agent PersonClass contracts Person {
    //(…)
    public void laugh(){
        System.out.println("I am laughing!");
    }
    //Eatable
    public void eat(){
        System.out.println("I am eating properly");
    }
}
public worker_agent Launcher {
    public static void test(with_compat Eatable eatableAgent){
        System.out.println("The agent will eat");
        eatableAgent.eat();
    }
    public static void main(String args[]){
        AnimalClass theMonkey = new AnimalClass("monkey", "4");
        PersonClass john = new PersonClass("John", 25);
        Launcher.test(theMonkey);
        Launcher.test(john);
    }
}
In the Java Framework:
// This interface can be extended only by a compat_interf_version with an agent-like role(abstraction, agent, simu_real_obj)
@Compat_interf_capacity(Advice.FOR_AGENT_LIKE)
public compat_interf_capacity Eatable {
    void eat(int quantity);
}
//We have to give the class role, because it has a capacity
@Agent
public interface Animal extends Eatable {
    int getAge();
    String getName();
    void setAge(int age);
    void setName(String name);
    void run();
}
//We have to give the class role, because it has a capacity
@Agent
public interface Person extends Eatable {
    void laugh();
}
//We can not write Eatable in the contracts, because it is a capacity.
@Agent
public class AnimalClass implements @Contracts Animal {
    //(…)
    public int getAge(){ //(…) }
    public String getName(){ //(…) }
    public void setAge(int age){ //(…) }
    public void setName(String name){ //(…) }
    public void run(){
        System.out.println("I am running");
    }
    //Eatable
    public void eat(){
        System.out.println("I am eating");
    }
    //
}
//We can not write Eatable in the contracts, because it is a capacity.
@Agent
public class PersonClass implements @Contracts Person {
    //(…)
    public void laugh(){
        System.out.println("I am laughing!");
    }
    //Eatable
    public void eat(){
        System.out.println("I am eating properly");
    }
}
@Worker_agent
public interface Launcher {
    public static void test(@With_compat Eatable eatableAgent){
        System.out.println("The agent will eat");
        eatableAgent.eat();
    }
    public static void main(String args[]){
        AnimalClass theMonkey = new AnimalClass("monkey", "4");
        PersonClass john = new PersonClass("John", 25);
        Launcher.test(theMonkey);
        Launcher.test(john);
    }
}
Capacities in Clprolf are always normal capacities, with a clear advice: they are either agent-like or worker-like, never both.
However, an interface from the other declension may still contract such a capacity when required. In this case:
Runnable).@Forc_int_inh.Example: Runnable is a worker capacity.
An agent interface can still extend it, but must declare it with @Forc_int_inh, showing that classes implementing this interface are temporarily seen as workers for execution.
A compat_interf_capacity can be declared without any advice annotation
(@Agent_like_advice, @Worker_like_advice, etc.).
Such interfaces are called neutral capacity interfaces.
Neutral capacities are designed for neutral compat_interf_version,
that is, version interfaces without any class role
(agent, worker_agent, model, information, indef_obj).
They define role-independent capabilities that may apply to both conceptual and technical worlds, but they do not carry any advice or semantic constraint by default.
Important: When a neutral capacity is used by a role-declared version, it is interpreted as role-bound (agent-like by default), according to [ARCH_BB8]. However, when used within a neutral version, it remains strictly neutral and context-independent.
Summary:
compat_interf_version.Clprolf provides features for developers who prefer to think in terms of inheritance for interfaces, treating them as if they were pure abstract classes. These features become mandatory whenever a version interface inherits from another version interface.
When with_compat is used, it is as if the API of the class were replaced by the implemented interface.
The object now belongs to the hierarchy of the interface, rather than the class — entering an implementation-less world where only interfaces define structure.
@Agent) may be added above an interface declaration to enforce coherence.The class implementing such an interface must declare the exact same class role — not just an equivalent synonym.
@Agent, the implementation must also be @Agent (not @Simu_real_obj).For this vision:
@Compat_interf_version = @Version_inh@Compat_interf_capacity = @Capacity_inh
(no class role may be written on a @Capacity_inh).Interfaces and concrete classes share the same inheritance hierarchy (or equivalent). This is why it is correct to say that a class inherits from an interface:
Example:
HorseImpl extends AnimalImpl and implements HorseHorse extends AnimalAnimalImpl implements AnimalEverything aligns, and we can say that HorseImpl inherits from both the class AnimalImpl and the interface Animal.
In Java, this is often called simulated multiple inheritance:
@Forced_inh (not @Forced_int_inh) must be used to enforce role coherence.@Nature is allowed on extends clauses of interfaces — even with multiple inheritance.This means:
⚠️ Multiple inheritance of natures is allowed but not recommended.
The nature keyword (or @Nature in the framework) indicates an inheritance perspective for the interface, rather than a simple extension.
@Agent) is present on an interface, @Version_inh (or @Compat_interf_version) is not mandatory.@Forced_int_inh is not mandatory.In the language syntax, however, the keyword must always be explicit:
public version_inh agent Teacher { ... }
By contrast, in the framework, annotations are sufficient and the explicit keyword is not required.
The features for interface inheritance allow developers to treat interfaces like classes, except without direct access to implementations.
In Clprolf, developers may choose to apply class roles to interfaces if they prefer an inheritance perspective.
@Version_inh and @Capacity_inh exist specifically for this vision.
Their use is optional, and multiple inheritance (other than capacity inheritance) is not recommended.
Interface inheritance features are therefore best applied for loose coupling with single inheritance in agent hierarchies.
The following example shows a basic and recommended use of interface inheritance in Clprolf.
It demonstrates how a simple interface hierarchy works when interfaces are tied to a class role (here, agent).
public version_inh agent Dog nature Animal {
    void bark(int duration);
}
public version_inh agent Animal {
    public void eat(String foodName);
}
public agent DogImpl nature AnimalImpl contracts Dog {
    public void bark(int duration){
        System.out.println("The dog is barking for " + duration + "s");
    }
}
public agent AnimalImpl contracts Animal {
    public void eat(String foodName){
        System.out.println("The animal is eating " + foodName);
    }
}
package org.clprolf.patterns.optfeaturesinterf.simpleintinh;
import org.clprolf.patterns.optfeaturesinterf.simpleintinh.impl.DogImpl;
import org.clprolf.patterns.optfeaturesinterf.simpleintinh.interfaces.Dog;
import org.simol.simolframework.java.With_compat;
import org.simol.simolframework.java.Worker_agent;
/**
 * Output:
 * The free impl dog: 
 * The dog is barking for 100s
 * The animal is eating meat
 * The dog impl: 
 * The dog is barking for 100s
 * The animal is eating meat
 */
public worker_agent Launcher {
    public static void main(String[] args) {
        // We can either use a dog with or without direct implementation
        with_compat Dog myFreeImplDog = new DogImpl();
        DogImpl myImplDog = new DogImpl();
        System.out.println("The free impl dog: ");
        myFreeImplDog.bark(100);
        myFreeImplDog.eat("meat");
        System.out.println("The dog impl: ");
        myImplDog.bark(100);
        myImplDog.eat("meat");
    }
}
This is the most common and recommended case of interface inheritance:
Dog and Animal) have a class role (agent).The implementation can then be used in two ways:
with_compat Dog),DogImpl).This Dog/Animal example demonstrates how simple interface inheritance works in Clprolf:
This is the recommended way to use interface inheritance in Clprolf, in contrast to multiple inheritance patterns, which are possible but discouraged.
Clprolf normally enforces single nature per object. However, the language also makes it possible to model multiple inheritance through interfaces. This chapter presents a design pattern that demonstrates how such hierarchies could be built.
⚠️ Important: Multiple inheritance is not recommended in Clprolf. Objects should normally have only one nature. This example is provided mainly for illustration.
@Agent // Optional on interfaces
@Version_inh
public interface Assistant extends @Nature Teacher, Student { 
}
@Agent
@Version_inh
public interface Person {
    int getAge();
    void setAge(int age);
    String getName();
    void setName(String name);
    void walk();
}
@Agent
@Forced_int_inh
@Version_inh
public interface Student extends @Nature Person {
    void learn();
}
@Agent
@Forced_int_inh
@Version_inh
public interface Teacher extends @Nature Person {
    void teach();
}
The implementation combines TeacherClass, StudentClass, and PersonClass through delegation.
This approach also enables code reuse, though the focus here is on demonstrating multiple inheritance.
@Agent // Must match the role of the interface
public class AssistantClass implements @Contracts Assistant, Teacher, Student {
    protected TeacherClass teacher;
    protected StudentClass student;
    protected PersonClass person;
    public AssistantClass(String name, int age){
        this.teacher = new TeacherClass(name, age);
        this.student = new StudentClass(teacher); // teacher contains the person part
        this.person = (PersonClass) this.teacher;
    }
    // Delegate Teacher role
    public void teach(){ this.teacher.teach(); }
    // Delegate Student role
    public void learn(){ this.student.learn(); }
    // Delegate Person role
    public int getAge() { return this.person.getAge(); }
    public void setAge(int age) { this.person.setAge(age); }
    public String getName() { return this.person.getName(); }
    public void setName(String name) { this.person.setName(name); }
    public void walk() { this.person.walk(); }
}
@Agent
public class PersonClass {
    protected class PersonProperties {
        private String name;
        private int age;
        public PersonProperties(String name, int age) {
            this.name = name;
            this.age = age;
        }
        // Getters and setters...
    }
    private PersonProperties sharedProperties;
    public void setSharedProperties(PersonProperties sharedProperties) {
        this.sharedProperties = sharedProperties;
    }
    public PersonProperties getSharedProperties() {
        return this.sharedProperties;
    }
    public PersonClass(String name, int age) {
        this.sharedProperties = new PersonProperties(name, age);
    }
    public String getName() { return sharedProperties.getName(); }
    public int getAge() { return sharedProperties.getAge(); }
    public void setName(String name) { sharedProperties.setName(name); }
    public void setAge(int age) { sharedProperties.setAge(age); }
    public void walk() {
        System.out.println(getName() + " is walking.");
    }
}
@Agent
public class StudentClass extends @Nature PersonClass implements @Contracts Student {
    public StudentClass(String name, int age) { super(name, age); }
    public StudentClass(PersonClass personTwin) {
        super(null, 0); 
        this.setSharedProperties(personTwin.getSharedProperties());
    }
    public void learn() {
        System.out.println(this.getName() + " is learning.");
    }
}
@Agent
public class TeacherClass extends @Nature PersonClass implements @Contracts Teacher {
    public TeacherClass(String name, int age) { super(name, age); }
    public TeacherClass(PersonClass personTwin) {
        super(null, 0);
        this.setSharedProperties(personTwin.getSharedProperties());
    }
    public void teach() {
        System.out.println(this.getName() + " is teaching.");
    }
}
This design pattern shows how Clprolf can technically support multiple inheritance through interfaces, while still allowing for code reuse via delegation.
⚠️ However, in real-world Clprolf development:
For collaborative projects — such as public APIs or large teams — it can be useful to assign class roles to interfaces, in order to make their purpose explicit and to enforce coherence.
To do this, you must use the features for interface inheritance:
version_inh (or compat_interf_version),agent, abstraction, etc.).This ensures that the compiler checks the coherence between the role of the interface and the role of its implementation classes.
package clprolf.wrappers.java.sql;
// Using a role-bound compat_interf_version (feature-equivalent form)
// Assigning a class role for clarity in collaborative projects
@Forc_int_inh
public compat_interf_version abstraction ClpConnection extends Connection {
}
Implementation classes must declare exactly the same role as the interface.
In this example, any class implementing ClpConnection must also be annotated as abstraction — not just an equivalent role.
compat_interf_version — Between Compatibility and FeaturesClprolf allows a compat_interf_version to declare a class role,
such as agent, abstraction, worker_agent, etc.
This case remains relatively rare,
but it is especially useful in collaborative or interoperability contexts,
such as public libraries or Java wrappers.
When a class role is attached to a compat_interf_version,
the interface remains a compatibility interface by nature —
it does not become a feature interface in syntax,
but it behaves as a role-bound version interface,
and thus is semantically equivalent to features.
This allows developers to explicitly express intent without switching to the full feature syntax.
Example:
package clprolf.wrappers.java.sql;
// Using a role-bound compat_interf_version (feature-equivalent form)
// Assigning a class role for clarity in collaborative projects
@Forc_int_inh
public compat_interf_version abstraction ClpConnection extends Connection {
}
Here:
compat_interf_version → preserves the compatibility form,
ideal for wrappers or API integration.abstraction → gives the semantic layer that ties it to a world.@Forc_int_inh → required since it extends another version (Java’s Connection).This form is therefore halfway between the purely structural version_inh
and the compatibility-oriented compat_interf_version,
offering a flexible way to handle APIs that mix both semantics.
Summary:
- ✅ A
 compat_interf_versioncan declare a class role.- ⚙️ It remains a compatibility interface, but behaves as feature-equivalent.
 - 🧩 Useful for wrappers, public APIs, and cross-language compatibility.
 - ⚠️ Inheritance from another version requires
 @Forc_int_inh.
Clprolf provides two equivalent syntactic forms for defining interfaces:
the feature-oriented form (with the _inh suffix)
and the compatibility-oriented form (compat_interf_...).
This duality allows developers to reuse existing interfaces
while expressing them through a different perspective:
implementation structure (_inh)
or compatibility semantics (compat_interf_...).
This requalification is purely syntactic — but the interface being defined always takes precedence. It is the keyword used in the current definition that determines the nature of the interface.
The defining keyword (version_inh, compat_interf_version, etc.)
always determines the semantic category of the interface.
The parent’s form has no impact on that nature.
// The defined interface is a version interface (feature-oriented),
// even though it inherits from a compatibility form.
public version_inh MyFeatureVersion extends compat_interf_version BaseInterface { }
Here, MyFeatureVersion remains a feature-oriented interface,
because the current definition (version_inh) defines its identity.
// The defined interface is compatibility-oriented,
// but it inherits from a version interface.
// This normally breaks the rule that versions cannot be chained,
// so a semantic forcing is required.
@Forc_int_inh
public compat_interf_version MyCompatVersion extends version_inh LegacyVersion { }
In this case, MyCompatVersion is compatibility-oriented,
but since compat_interf_version interfaces are not allowed to inherit from versions
(whether they are version_inh or other compat_interf_version),
the use of @Forc_int_inh explicitly authorizes this exception.
version_inh ↔ compat_interf_version — interchangeable forms.compat_interf_version cannot inherit any version
(version_inh or compat_interf_version) without @Forc_int_inh.Clprolf now introduces a refined and mature approach to language annotations — a model that eliminates mechanical redundancy while keeping full expressive clarity. These annotations are no longer external metadata: they are words of the language itself.
Clprolf annotations are marker annotations only — lightweight, structural tags understood directly by the compiler. They are written naturally, without imports or fully qualified names:
@Expert_component
public agent Engine { }
No import statements are needed, and none are ever generated. The compiler knows exactly what they mean — because they belong to the language.
The annotations no longer live in files. They live in Clprolf’s own vocabulary. 🌿
During Java code generation, all Clprolf annotations are removed. They are used only to guide semantic understanding, then disappear, leaving clean, standard Java output.
public class Engine { }
The meaning remains preserved inside the compilation process, not in the mechanical result.
What guided the design does not need to appear in the code. 💫
Clprolf allows developers to use any type name — even one that matches a reserved annotation name — as long as the Clprolf version of that annotation is not used.
Example:
import org.me.Static   // ✅ allowed
// ... no @Static Clprolf used in this file
But if a Clprolf annotation @Static is used in the same file,
then any external import of Static becomes illegal.
[ARCH-Gx] Illegal import of reserved annotation name: Static
(use @Clp_Static if you need your own definition)
💡 This rule keeps the language free and consistent: you can use any name you want — unless it already has a role in the Clprolf world.
For each built-in annotation, a synonym exists with the prefix Clp_,
for example @Clp_Static, @Clp_Expert_component, etc.
These synonyms serve as escape routes for developers
who need to use a similar name without clashing with Clprolf’s built-ins.
The
Clp_prefix is a bridge — a respectful handshake between your code and the language itself. 🌿
Clprolf no longer relies on annotation source files, nor on Java imports to understand its own vocabulary. Everything is built into the language itself — compact, consistent, and self-sufficient.
The compiler checks what matters: only the imports written by the developer. If one of them reuses a reserved Clprolf name and that annotation is active in the file, Clprolf raises an error. Otherwise, it stays silent.
The language knows when to speak — and when to let you breathe. 🌿
This evolution reflects Clprolf’s deeper truth: to be clear without being heavy, to be structured without being rigid, and to protect its meaning while staying open to the world.
No imports. No source files. No redundant mechanics. Only understanding — pure and precise.
Clprolf does not imitate Java. It finishes what Java began. 💫
Clprolf is fully interoperable with Java.
It relies on Java 8 syntax and semantics for all code embedded in .clp files,
while allowing external Java sources to target any version of the JVM.
All Java types are imported explicitly through typed import statements:
import java_class fully.qualified.ClassName;
import java_interface fully.qualified.InterfaceName;
Optionally, these imports may include a semantic declaration and even Clprolf annotations to define how the Java element behaves within Clprolf:
import java_interface version_inh abstraction java.util.List;
@Expert_component
import java_class agent java.util.Timer;
This mechanism makes any Java library appear as a Clprolf-native library, verified semantically and integrated into the same conceptual framework. Each imported type becomes a true Clprolf entity, subject to the same architectural rules as native components.
💡 Clprolf does not wrap Java — it understands it.
Clprolf is not only about object-oriented design — it is also algorithm-centric. Its roles and structures are designed to make writing implementations easier and more intuitive.
To this end, Clprolf adds several algorithmic enhancements:
underst,@One_at_a_time, @Turn_monitor, @For_every_thread),The goal is to make algorithm writing as natural as possible, so programmers can focus on the logic of the algorithm, rather than the technical details of synchronization.
Imagine a hypermarket with a single main queue that dispatches customers to several checkouts. Each customer must read the screen to know which checkout is free — but only one at a time.
In Clprolf, this scenario can be expressed directly with annotations:
@One_at_a_time models the fact that only one customer can access the screen at once.@Turn_monitor ensures that all customers waiting in the same queue share the same lock.@For_every_thread allows each customer’s life cycle to run independently, like real people moving in parallel.@Agent
public class Customer implements @Contracts Runnable {
    private String name;
    @For_every_thread
    private volatile boolean blnContinue;
    @Turn_monitor
    private Object firstQueueMonitor;
    @Turn_monitor
    private Object secondQueueMonitor;
    public Customer(String name, Object first, Object second){
        this.name = name;
        this.firstQueueMonitor = first;
        this.secondQueueMonitor = second;
    }
    public void run() {
        this.blnContinue = true;
        while (blnContinue) {
            this.waitToFirstMainQueue();
            this.waitToSecondMainQueue();
        }
    }
    @One_at_a_time
    public void waitToFirstMainQueue(){
        synchronized(firstQueueMonitor){
            System.out.println(name + " is waiting in the first queue...");
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            System.out.println(name + " got a checkout in the first queue!");
        }
    }
    @One_at_a_time
    public void waitToSecondMainQueue(){
        synchronized(secondQueueMonitor){
            System.out.println(name + " is waiting in the second queue...");
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            System.out.println(name + " got a checkout in the second queue!");
        }
    }
}
With these enhancements, Clprolf makes concurrency and parallelism visible and understandable directly in the code. It becomes immediately clear that:
This demonstrates Clprolf’s philosophy: bringing clarity and human-like readability to algorithmic programming.
long_action MODIFIERAlongside underst, Clprolf introduces another method modifier: long_action.
This modifier marks methods — especially in agent classes — that represent actions unfolding over time. A typical example would be the movement of a video game enemy, implemented as a loop.
All such methods are declared with long_action. They are executed step by step within a dedicated thread for the object. This approach is particularly useful in game development, though not limited to it.
The pattern works as follows:
walk().continueWalk().endLongActions() method, which the developer can call to advance all ongoing actions in sync.For example, in a video game, endLongActions() could be invoked inside the paint() method of the graphical container, ensuring smooth updates.
This design preserves an action-oriented perspective, while internally emulating threads. A boolean flag (annotated with @Long_action in the Java framework) is typically required to manage state.
In the framework, a single @Long_action annotation covers all use cases, keeping the approach simple and consistent.
prevent_missing_collision MODIFIERThe prevent_missing_collision modifier (or @Prevent_missing_collision annotation in the Java framework) is primarily used in agent classes.
Its purpose is to simplify concurrency (especially when combined with long_action) and parallelism (multi-threading) in real-time simulations. When applied, it ensures that interactions or collisions are never lost, even if methods run in parallel threads.
For example, a setPosition() method in a video game could be marked with prevent_missing_collision. To guarantee consistency, all related methods — such as getPosition() — should also be marked the same way. The framework then synchronizes these methods automatically, preventing missed collisions or desynchronized states between players, enemies, or other simulated entities.
To simplify the management of parallelism, Clprolf introduces four modifiers (with equivalent annotations in the Java framework):
one_at_a_time (method modifier): ensures that only one thread at a time can execute the method or block of code, similar to synchronized.turn_monitor (attribute modifier): applied to a lock object to make its role in synchronization explicit.for_every_thread (attribute modifier): applied to volatile attributes, highlighting their importance in parallel execution.dependent_activity (method modifier): marks methods that call wait() on a monitor object, identifying them as dependent on other threads.A method annotated as dependent_activity explicitly depends on the activity of another thread. This is similar to the producer–consumer pattern, but Clprolf emphasizes an algorithmic perspective rather than a purely technical one.
Instead of focusing on wait() and notify() as low-level mechanisms, Clprolf lets developers express the idea directly: “this action depends on another activity.” This makes algorithms easier to reason about, implement, and test.
For example, in a hypermarket simulation:
This abstraction reduces complexity, helps prevent errors, and keeps the focus on the intended algorithmic behavior.
@Abstraction
public class OneMessageMailBox {
    private String message;
    @For_every_thread // Highlights its use in parallelism
    private boolean full;
    @Turn_monitor
    private final Object mailBoxMonitor;
    public OneMessageMailBox() {
        this.mailBoxMonitor = new Object();
    }
    @Dependent_activity
    @One_at_a_time
    public String read() {
        synchronized (mailBoxMonitor) {
            while (!this.full) {
                try {
                    mailBoxMonitor.wait(); // Wait until a message is available
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            this.full = false;  // Mailbox is now empty
            mailBoxMonitor.notifyAll(); // Signal waiting writers
            return this.message;
        }
    }
    @Dependent_activity
    @One_at_a_time
    public void write(String message) {
        synchronized (mailBoxMonitor) {
            while (this.full) {
                try {
                    mailBoxMonitor.wait(); // Wait until the mailbox is empty
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            this.message = message;
            this.full = true; // Mailbox is now full
            mailBoxMonitor.notifyAll(); // Signal waiting readers
        }
    }
}
In Clprolf, the recommended approach is to start with pure concurrency in a single thread before introducing parallelism. Many simulation actions take time to run and are not just instantaneous state changes.
long_action modifier (@Long_action in the Java framework) allows actions to be executed step by step.prevent_missing_collision modifier (@Prevent_missing_collision) ensures correctness.This model often suffices for real-time simulations. If threads are later introduced, they must sometimes be synchronized. However, synchronized parts of code behave almost as if there were still a single thread, so the added complexity must be carefully evaluated.
When synchronization is necessary:
prevent_missing_collision.one_at_a_time modifier (@One_at_a_time) applies to parallelism, enforcing that only one thread executes the code at a time.turn_monitor modifier groups these synchronized sections around a common monitor object.These notions are compatible with existing Java mechanisms like synchronized and lock, but Clprolf emphasizes a higher-level, less technical perspective that highlights algorithmic intent rather than implementation detail.
Finally, problems that are purely parallel — especially those involving dependent activities — can be implemented directly with multiple threads.
underst MODIFIERThe underst modifier (short for understanding) can be applied to methods in agent or worker_agent classes. It marks methods that involve some form of computer understanding — for example, recognizing objects in an image.
It can also be used to highlight code that is non-intuitive or difficult to follow, such as complex sorting algorithms. Even well-known algorithms can be annotated with underst if their implementation is considered non-trivial.
Syntactically, underst is placed before the return type in a method declaration. It cannot be used on methods within compatibility interfaces.
Example:
public agent ImageAnalyzer {
    // Method marked as 'underst' because it performs recognition
    public underst boolean recognizeObject(Image img) {
        // Complex recognition logic here...
        return true;
    }
    // Another example: a non-trivial sort
    public underst void optimizedSort(List<Integer> values) {
        // Advanced sorting algorithm...
    }
}
The Clprolf compiler is the most direct way to use the language. However, a Clprolf framework also exists for Java developers.
During compilation, Clprolf keywords and annotations are translated into standard Java syntax as follows:
class
agent, worker_agent, comp_as_worker,
abstraction, simu_real_obj,
model, information, indef_objinterface
compat_interf_version, compat_interf_capacity,
compat_interf, version_inh, capacity_inhOther keywords → removed
class_for, underst, with_compat, long_action,
prevent_missing_collision, turn_monitor, one_at_a_time,
for_every_thread, dependent_activity,
java_class, java_interface
These keywords are used only for semantic analysis inside Clprolf and have no equivalent in generated Java code.
nature → extends
contracts → implementsAnnotations
Clprolf annotations are preserved in generated Java code except when applied to import declarations (since Java does not allow them).
They have no technical impact but serve as semantic documentation.
Ignored or preserved annotations include:
@Human_expert, @Expert_component,
@Human_expert_static, @Expert_component_static,
@Static,
@Long_action, @Forc_inh, @Forc_int_inh,
@Forc_pract_code, @Agent_like_advice, @Worker_like_advice.
✅ Summary
import lines.Clprolf’s compiler does not merely translate keywords into Java code; its semantic rules act like continuous architecture tests. Each build validates that classes, interfaces, and capacities still respect their declared roles and relationships. This turns compilation into a first level of non-regression testing for architecture: even after major refactoring, developers receive immediate feedback if a class crosses a forbidden boundary, if a capacity is misused, or if an agent/worker separation is broken.
Although not all semantic mismatches can be detected automatically, these built-in checks guarantee the essential structural integrity of the system. They ensure that a project remains faithful to its design principles over time, reducing the risk of silent architectural drift that often occurs in large codebases. In this sense, Clprolf brings to compilation what automated tests bring to runtime: a safety net for meaning, not just for syntax.
Declensions (roles) in Clprolf allow semantic checks to be performed by the compiler or by external tools. These checks ensure coherence in class and interface design. They can be overridden with @Forced_inh, @Forced_int_inh, or @Forced_pract_code (both in the Clprolf language and in the Java framework).
The purpose of these checks is to prevent contradictions in how declensions are applied. For example, a Fruit class declared as a worker_agent could not be the parent of an Apple class declared as an agent.
A capacity is always about shared functionality across multiple version interfaces, and always targets either agent or worker_agent classes.
At the same time, Clprolf preserves freedom of interpretation by allowing developers to override checks with forced keywords when needed.
The guiding principle is simple: the rules reflect the programmer’s intuitive sense of coherence when using Clprolf. They are applied only to the direct inheritance level (not transitive inheritance), which makes them easier to learn and apply.
Class inheritance contradictions
agent must inherit from an agent; a worker_agent must inherit from another worker_agent.Contracts contradictions
compat_interf_version (a class represents one version only).compat_interf_capacity (or capacity_inh).Interface inheritance contradictions
compat_interf_version cannot extend another compat_interf_version, nor can a compat_interf_capacity be composed of a version.@Agent_like_advice).System abstraction usage contradictions
File, Socket, etc.) can be used only by worker_agent or abstraction classes.agent uses @Forced_pract_code for small amounts of technical code.Sub-roles also follow consistency checks:
@Human_expert, @Expert_component are equivalent.@Human_expert_static and @Expert_component_static are equivalent.@Static is not equivalent to other static roles. A purely static role cannot inherit from a non-static role, and vice versa (except if both are abstraction roles).Each class or interface must declare its role explicitly, even if it inherits, because the author is responsible for indicating their perspective. Declaring sub-roles is recommended to avoid future inheritance issues.
Direct inheritance from Java classes or interfaces is not allowed, except with @Forced annotations.
Inheritance checks can be bypassed using @Forced_inh (for classes) and @Forced_int_inh (for interfaces). These can be applied either at the class/interface level, or directly before the inherited type.
Example:
/* All inherited classes are accepted in inheritance, even if inconsistent */
@Forced_inh
@Agent
public class Car extends CarRealization {
   //(...)
}
or
@Agent
public class Car extends @Forced_inh CarRealization {
   //(...)
}
with
/* CarRealization handles displays and input for the Car simulation */
@Worker_agent
public class CarRealization {
   //(...)
}
A compiler for Clprolf is implemented in Java, using ANTLR4 and based on the official Java 8 grammar (from the antlr4-grammars repository).
.simo) as well as embedded Java 8 code.javac, producing standard Java bytecode executables.The Clprolf compiler itself is written in Clprolf, using the Clprolf framework as its structural backbone. This makes Clprolf not only a language and a methodology, but also a self-hosted system — its own compiler is built with the same principles it enforces.
This self-reference demonstrates Clprolf’s maturity and internal coherence:
In short: Clprolf compiles Clprolf — powered by its own framework.
The Clprolf compiler, written in Clprolf itself using the Clprolf framework, has now entered its semantic phase. It already implements several semantic rules (4 as of now), which are gradually being added and refined.
The current compiler version still focuses primarily on syntax analysis and code generation, but semantic checking has become an integral part of its ongoing evolution.
The Clprolf Semantic Checker is active and growing. It performs rule-based analysis on declensions, contracts, genders, and inheritance coherence, operating directly on the symbol table generated during parsing.
In parallel, a dedicated Framework Checker is also being developed. It reuses the same semantic engine, but with a specialized symbol table visitor. This enables it to validate framework-level structures (wrappers, capacities, version interfaces, and practical components) without duplicating compiler logic.
This modular architecture allows both the compiler and the framework checker to share a unified rule engine — ensuring semantic consistency across the entire Clprolf ecosystem.
💡 In short, Clprolf is no longer just a parser — it is becoming a self-hosted semantic environment, where its compiler, framework, and rule engine all evolve together within the same language.
Below is a short excerpt from the Clprolf compiler, written with the Clprolf framework. It shows how semantic verification is organized — using clear roles, coherent structure, and object responsibility, all defined in Clprolf style.
@Agent
package org.clprolf.compiler.semantic.agents.impl;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import org.clprolf.framework.java.Agent;
import org.clprolf.compiler.semantic.abstractions.impl.SemanticSymbol;
import org.clprolf.compiler.semantic.enums.CompatInterfaceDeclSynonym;
import org.clprolf.compiler.semantic.enums.Declension;
import org.clprolf.compiler.semantic.abstractions.impl.SemanticInterfaceSymbol;
import org.clprolf.compiler.semantic.abstractions.impl.SemanticClassSymbol;
public class SemanticCheckerImpl {
    private final Map<String, SemanticSymbol> symbols;
    private final List<String> errors = new ArrayList<>();
    public SemanticCheckerImpl(Map<String, SemanticSymbol> symbols) {
        this.symbols = symbols;
    }
    public List<String> getErrors() {
        return errors;
    }
    // -------------------------------------------------------------
    // 🧠 Entry point
    // -------------------------------------------------------------
    public void verify() {
        for (SemanticSymbol s : symbols.values()) {
            if (s instanceof SemanticClassSymbol) {
                verifyClassRules((SemanticClassSymbol) s);
            } else if (s instanceof SemanticInterfaceSymbol) {
                verifyInterfaceRules((SemanticInterfaceSymbol) s);
            }
        }
    }
}
Excerpt from the current Clprolf compiler — showing the beginning of the semantic rule engine, implemented directly through the Clprolf framework.
Clprolf source files can be edited with common tools:
The Clprolf framework for Java integrates fully with the Java ecosystem:
To make it easier for developers to use existing Java libraries within Clprolf, a classification of common Java libraries is proposed and will continue to grow.
For example:
@Abstraction
public class JPanel extends JComponent 
    implements java.awt.ImageObserver, java.awt.MenuContainer { ... }
or
@Compat_interf_capacity
public interface MenuContainer { ... }
Here, JPanel is expressed as an abstraction, while MenuContainer is treated as a capacity interface, since it represents a cross-family capability that different UI components can implement.
These annotations illustrate how existing Java code can be expressed in Clprolf terms. The goal is not to cover every library exhaustively, but to provide guidance that helps Clprolf users integrate familiar Java components into their projects.
The Clprolf framework offers an elegant way to make writing Java code easier and more enjoyable. Equivalent versions are also available for C# and PHP.
Clprolf provides solutions that combine ease of use with high code quality. It is not only useful for teaching, but also for developers who simply want more facilitating tools in their daily work.
This includes:
The Clprolf framework is a package of Java annotations (or C# / PHP attributes) that provides developers with a toolbox for applying Clprolf concepts directly within their host language.
It allows you to think in Clprolf while programming in Java, C#, or PHP 8.
With the framework, development in the target language remains the same at its core, but annotations change how we structure systems:
Thus, we continue to use the host language (e.g., Java or C#), but with Clprolf roles and semantics layered on top.
In practice, you can still keep conventional class names (e.g., InvoiceService) while adding annotations to define their Clprolf role.
For example, the Java framework could be described as “Java with agents.”
These annotations are designed to be paired with an executable that performs checks for coherence — similar to a compiler.
The package org.clprolf.simolframework.java provides the following annotations:
Class roles:
@Agent, @Abstraction, @Simu_real_obj,
@Worker_agent, @Comp_as_worker,
@Model, @Information, @Indef_obj.
Interface roles:
@Compat_interf_capacity, @Compat_interf_version, @Compat_interf.
Modifiers and constraints:
@With_compat, @Nature, @Contracts,
@Forced_inh, @Forced_int_inh, @Forced_pract_code,
@Version_inh, @Capacity_inh.
Behavioral annotations:
@Underst, @Long_action, @Prevent_missing_collision,
@One_at_a_time, @For_every_thread, @Turn_monitor, @Dependent_activity.
@Abstraction
public class Car { /* (...) */ }
@With_compat UserDao daoUser;
@Underst // Recognize object in an image
public void recognizeObject() { }
@Compat_interf_capacity(Advice.FOR_AGENT_LIKE)
public interface MySortable { }
Annotations are placed in the same locations as in pure Clprolf — before class declarations, interface definitions, methods, or types (e.g., @With_compat on variables, with the exception of method return types).
The Clprolf Framework can operate in two complementary modes, depending on how strictly you wish to follow the language rules.
In Strict Mode, all Clprolf annotations must be written explicitly —
@Nature, @Contracts, and @With_compat are mandatory.
This mode mirrors the pure language behavior, ensuring total transparency of intent and perfect semantic control. It is the preferred mode for teaching, architecture validation, and formal projects, where every structural element must be explicitly visible and verified by the compiler.
In Flexible Mode, the same annotations become optional.
If @Nature, @Contracts, or @With_compat are omitted, the compiler automatically interprets them as present and applies their semantics.
This keeps the framework lightweight and enjoyable to use in everyday Java, C#, or PHP projects, while maintaining full compliance with Clprolf’s conceptual model. The resulting code remains concise, practical, and free of unnecessary boilerplate — yet semantically equivalent to the strict version.
💡 Flexible Mode is the default behavior of the framework, designed to make Clprolf concepts naturally usable in host languages, without friction.
| Mode | Annotations Required | Typical Use | Goal | 
|---|---|---|---|
| Strict Mode | All annotations explicit | Teaching, validation, research | Full semantic visibility | 
| Flexible Mode | Optional key annotations (@Nature, @Contracts, @With_compat) | 
Everyday projects, frameworks | Simplicity with preserved semantics | 
| Category | Annotations | 
|---|---|
| Class Roles | @Agent, @Simu_real_obj, @Abstraction, @Worker_agent, @Comp_as_worker, @Model, @Information, @Indef_obj | 
| Interface Roles | @Compat_interf_capacity, @Compat_interf_version, @Compat_interf, @Version_inh, @Capacity_inh | 
| Modifiers & Constraints | @With_compat, @Nature, @Contracts, @Forced_inh, @Forced_int_inh, @Forced_pract_code | 
| Behavioral Annotations | @Underst, @Long_action, @Prevent_missing_collision, @One_at_a_time, @For_every_thread, @Turn_monitor, @Dependent_activity | 
Since C# is close to Java, a Clprolf framework is also available for C#. It provides attributes similar to Java annotations, allowing C# developers to benefit from Clprolf’s methodology.
nature and contracts are not included, due to C# attribute limitations. This is not critical, since C# already uses : for inheritance and implementation, and once developers understand Clprolf’s philosophy, the intent remains clear.with_compat is available for fields and parameters, but not for local variables.I, making them easily distinguishable.Forced_inh, Forced_int_inh, etc.) are applied only at the class or interface definition level, again due to C# attribute limitations.A Clprolf framework also exists for PHP 8.
nature and contracts are not available due to attribute limitations.with_compat cannot be applied to local variables.turn_monitor, for_every_thread, one_at_a_time, dependent_activity) are not included, since PHP does not support threading natively.In Clprolf, every object is treated as a component. A component, by definition, has a single, unique responsibility. If an object takes on multiple unrelated responsibilities, it no longer qualifies as a component.
By assigning each object a basic declension (its nature), Clprolf ensures that every OOP object is a well-formed component. The resulting system is therefore a set of components collaborating through action calls.
simu_real_obj, comp_as_worker, etc.) can also be applied in the same way.Traditional roles such as controller, service, or repository can still be layered on top of these basic roles. This means Clprolf stays fully compatible with existing design practices.
Clprolf does not reinvent OOP principles — it classifies and integrates existing best practices:
These practices are already well known in OOP. What Clprolf adds is the ability to embed them directly into the language, making design choices more intuitive and systematic.
With Clprolf, components are not just technical units: they become actors in a system. Designing an application therefore begins by choosing its agents (or worker_agents), which serve as the foundation for the architecture.
The Clprolf language is especially compatible with the S.O.L.I.D. principles. Here is how each principle is supported.
The choice of a declension and optional gender guarantees a unique responsibility, since each carries a precise and well-defined role.
The nature keyword ensures that inheritance remains coherent.
Interface inheritance features assign a role to the targeted object, enforcing single responsibility in future extensions.
The compiler checks declensions for both classes and interfaces, ensuring coherence throughout the system.
Clear object natures, class roles, and interfaces naturally enforce the open/closed principle. The design remains open for extension but closed for modification, thanks to explicit roles and targeted abstractions.
Class hierarchies are guaranteed to belong to the same family, through the nature keyword, declensions, and genders.
This makes Liskov substitution straightforward and reliable.
Clprolf distinguishes two main interface types: versions and capacities. Capacity interfaces refine version interfaces, adding cross-cutting functionality. With interface inheritance features, roles can be specified even more precisely, ensuring that every interface method is justified and useful.
The with_compat modifier makes the use of interface types explicit, making dependency injection immediately visible.
Features for interface inheritance allow interface hierarchies to mirror their class counterparts (version_inh), enabling clear abstractions and direct loose coupling.
Clprolf offers a perspective similar to multi-agent systems (MAS). The key difference is that in Clprolf, every abstraction with methods is considered an agent, even if it appears passive. By contrast, purely computational or technical code is assigned to worker_agent roles.
This perspective can help beginners understand Clprolf concepts more easily, and may also be of interest to MAS practitioners.
In Clprolf, a system is built from two main kinds of components:
Equivalent synonyms such as abstraction or simu_real_obj may also be used.
There are no additional object categories in the language.
For those who want to stay closer to MAS conventions, Clprolf provides the optional sub-role Gender.ACTIVE_AGENT.
This can be used to mark an agent explicitly as “active” in MAS terms.
@Agent or any equivalent qualifier, and restrict @Agent to active agents if desired.The difference from traditional MAS approaches is that Clprolf applies the MAS perspective universally. Every software built with Clprolf is, in essence, a multi-agent system:
Clprolf was not designed exclusively for MAS users, but it can be adapted for them when closer alignment is needed — particularly around the notion of active agents.
Object roles in Clprolf remain flexible.
For example, one may use the abstraction keyword for a class like Thread if it feels more appropriate, or simu_real_obj in another case.
Developers can also use agent and worker_agent roles without explicitly working in a MAS context.
This flexibility makes role assignment an interesting and expressive design choice.
In traditional OOP, a class is identified only by its name. Clprolf goes further by explicitly stating the role of the class.
A class name alone is often insufficient to convey its full responsibility.
Names usually reflect a concept (e.g., Horse, Connection), but this may not immediately reveal the role of the class.
Reading the source code can sometimes clarify the role, but this becomes impractical for larger implementations.
By contrast, Clprolf requires each class to declare its role. This role is both:
Since all objects originate from classes, clear and well-defined roles are essential to building coherent systems.
Clprolf invites you to see programming as a form of storytelling. You describe the characters (objects), the scenes (interactions), and the unfolding of the story (the system’s behavior).
The programmer becomes something like a writer, shaping a narrative through components and their interactions.
By providing clear object roles, well-defined interfaces, and built-in support for algorithmic design — including concurrency and parallelism — Clprolf makes this storytelling mindset natural and intuitive.
Traditionally, programmers tend to write code as if they were the computer. When describing the execution, we often speak in the computer’s voice: “he does this,” rather than “I do this.”
In Clprolf, object roles provide a different perspective. They define who performs the action, and establish a third-person view of execution.
The distinction can be compared to video games:
For example:
The object role (the who) combined with the third-person perspective (the what) creates a powerful algorithmic enhancement.
🧩 Occasional Use of the First-Person View
Clprolf does not exclude the first-person view entirely. In certain low-level or algorithmic contexts, it can still be natural — and even necessary — to think or express code in a subjective way:
In those cases, the developer temporarily “enters” the worker’s point of view — not as the author of the program, but as the voice of the executing agent itself.
This is still coherent with Clprolf’s philosophy: the system remains described from the outside (third-person), but specific actions may be written as if performed from within.
🌿 The third-person defines the architecture; the first-person expresses the action.
The Clprolf framework, with its clear roles and third-person view, makes it possible to design controlled, high-level systems. This approach allows programmers to model execution more objectively and coherently.
Pure object-oriented programming defines what an object is — a bundle of variables and methods — but it does not tell us how to design our objects.
Clprolf provides guidance for this design process. By assigning roles such as agent, worker_agent, or model, it helps us imagine how to create our classes so that the resulting design is:
The resulting objects remain pure OOP objects, but now with roles that explicitly reflect their responsibility — for example, an agent representing a real-world entity or abstraction.
Assigning a role means choosing a primary responsibility, directly in line with the Single Responsibility Principle (SRP).
Clprolf roles enable:
Thus, the compiler itself participates in the object design process.
Clprolf maintains an object-centric mindset fully compatible with OOP practices and habits.
Traditional OOP has always needed external guidelines such as design principles or design patterns — proof that developers benefit from structured support when designing their classes and objects.
Clprolf object roles bring this support directly into the language, turning best practices into built-in guidance.
In object-oriented programming, an object should be more than just a set of data. Its role — its essence — is a fundamental aspect of OOP design.
Thus, the question of an object’s nature belongs fully to the scope of OOP.
Every application on a computer falls into one of two categories:
In both cases, the ultimate objective of the computer is always tied to the final application that serves the user.
For this reason, the different kinds of objects in programming can only be understood as:
This perspective offers a more scientific vision of what an application really is: a composition of objects that model reality and objects that handle computation.
By bringing these perspectives together, Clprolf unifies all types of objects found in object-oriented programming.
One of the main goals — perhaps the most important — in designing Clprolf was to make it possible to write programs that would otherwise seem impossible or extremely difficult to create.
The language focuses on making objects and class components intuitive, direct, and even enjoyable to work with. Programming in Clprolf should feel almost natural, turning coding into a task that is both manageable and fun.
Beyond simplifying the act of writing code, Clprolf encourages developers to:
The conception of applications thus becomes more human-like, creative, and approachable, while remaining rigorous.
Clprolf was inspired by scientific domains such as physics, chemistry, and weather forecasting — all of which rely heavily on simulation and modeling. Video games also played a role, as they are practical examples of real-time simulations. At the same time, management IT was always present in the background, grounding the language in everyday software needs.
From the beginning, Clprolf aimed to:
At its origin, the motivation was simple: to create an easier and better way to practice object-oriented programming, while keeping it interesting. This vision was always balanced with a strong determination to integrate established paradigms and principles, rather than reinvent what already exists. 👉 Clprolf can thus be seen as a programming paradigm in itself, one that integrates methodology directly into the language while staying fully compatible with object-oriented programming.
Java was chosen as the underlying language because it aligns perfectly with Clprolf’s philosophy and mindset. It is powerful yet logical, and maintains a relatively minimalistic design.
Key reasons include:
While Java was the natural choice, Clprolf is not limited to it. Other languages such as C# are also strong candidates, and PHP is well suited for web and scripting contexts.
The Clprolf language and framework are naturally aligned with Domain-Driven Design (DDD).
According to Wikipedia, “Domain-driven design (DDD) is a major software design approach, focusing on modeling software to match a domain according to input from that domain's experts. Under domain-driven design, the structure and language of software code (class names, class methods, class variables) should match the business domain. For example, if software processes loan applications, it might have classes like ‘loan application’ and ‘customer’, with methods such as ‘accept offer’ or ‘withdraw’.”
Clprolf embodies this philosophy by design. Its structure inherently enforces the principle that classes and methods reflect the business domain, making DDD not an external practice but an intrinsic feature of the language.
Clprolf gives developers freedom in how they interpret and design classes. The same functionality can be modeled in different ways depending on perspective. For instance, business logic could be represented as the responsibility of a business expert — using an agent. Others might prefer to treat it as a technical task — using a worker_agent.
This flexibility allows Clprolf to accommodate different design sensibilities while keeping the system coherent.
In Clprolf, a traditional OOP class corresponds to a class_for object. This generic form can easily lead to God objects — classes that try to handle everything at once.
To prevent this, Clprolf provides more specific class roles, guiding developers toward clear, focused responsibilities and reducing the risk of oversized, monolithic classes.
agent, which simulates a real-world object,
– a worker_agent, which simulates the computer acting as a worker.
In traditional OOP everything is an object, but in Clprolf every object is explicitly one of these two declensions.worker_agent represents the computer as a worker (even though all workers are part of the same physical computer). An agent represents a real-world entity, with code that simulates its behavior. In practice, agent classes are often simpler to design and use, since they just reproduce recognizable real-world behaviors.agent or a worker_agent, each role mimics a real-world reality — either the entity itself or the computer-as-worker that supports it.worker_agent. If it is a direct simulation of reality (e.g. a Horse class), use an agent.worker_agent classes. The nature keyword enforces that responsibilities remain unique and consistent.model — equivalent to entities in classical OOP (no behavior, only attributes, often for persistence or database mapping).
– information — raw data structures meant for use by worker_agent classes. These should be used sparingly, whereas model is common (e.g. a Client entity).worker_agent classes should not be used solely for calculations. Calculations that belong to the business or simulation domain must stay inside agent classes (for instance, physics computations inside a simulation of a physical process). Only in special cases, such as system programming or technical libraries, should a worker_agent directly implement calculation code.Declensions enforce separation and clarity Declensions ensure that classes remain well-structured, each with a distinct responsibility. The same principle applies to interfaces: assigning a declension guarantees that each interface has a clear purpose and meaning.
nature maintains coherent inheritance
The nature keyword enforces consistency when a class inherits from another of the same declension. This applies only to classes, not interfaces.
While a compiler cannot automatically detect all semantic mismatches, basic AI-like checks could help — for example, preventing a class Tiger from inheriting from Vehicle. In Clprolf, developers can explicitly enforce inheritance even when such a semantic error is detected, acknowledging the exception. The nature keyword is therefore both a safeguard and a guide for programmers, whether or not AI-like validation is used.
Declensions guide growth by inheritance Inheritance is a natural way for a class to grow, but it can easily blur the original design. Declensions make it possible for the compiler to apply semantic rules that preserve meaning and coherence during inheritance. These rules ensure that only consistent declensions are combined. The same reasoning extends to interfaces: assigning roles to them enables the compiler to validate that their inherited forms retain their intended sense.
In short, semantic checks in Clprolf — powered by declensions and nature — safeguard the integrity of both classes and interfaces as they evolve through inheritance.
Clprolf includes role annotations to remain accessible to common interpretations of classes and to clarify the use of agent.
From another perspective, agent and worker_agent can both be seen as variations of the same root concept: the worker_agent. An agent is essentially a specialized worker_agent, focused on simulating real-world entities. Similarly, a model can be viewed as a more specific form of information.
With this observation, Clprolf can be mapped back to paradigms that treat all classes uniformly. In effect, one could see the language as consisting only of worker_agent classes (and information for data), aligning with the simpler view of classical OOP or even procedural programming.
In summary, it is as if agent were derived from worker_agent, and model from information. This perspective provides a conceptual bridge between Clprolf and existing programming paradigms.
nature VERSUS extendsIn traditional OOP, the extends keyword emphasizes inheritance in a broad sense.
In Clprolf, the nature keyword takes a more restrictive approach: it allows inheritance only when classes truly share the same nature. This avoids purely technical or arbitrary inheritance and encourages composition in other situations.
By design, nature helps prevent misuse of inheritance for both agent and worker_agent classes. If Java supported multiple inheritance, nature would also reduce risks such as the classic diamond problem.
ALGOL (Algorithmic Language) was designed with a strong emphasis on algorithmic and mathematical computation. Its goal was to provide a language for expressing algorithms clearly and efficiently. ALGOL 60 in particular was highly influential: it introduced features for structured programming and laid the foundation for many modern programming languages.
Clprolf, with its worker_agent declension (simulation of the computer as a worker), shares a similar orientation toward algorithmic programming. This declension explicitly represents the computer as an executor of algorithms, echoing ALGOL’s original ambition as an algorithmic language.
agent declension directly represents real-world objects, reinforcing this perspective.Teaching advanced programming concepts to children is challenging, especially with Java. Clprolf — or the Clprolf framework — can serve as an easier entry point to Java.
By introducing declensions such as agent, human expert, machine tool, or computer as worker, Clprolf provides intuitive metaphors that make it easier to explain complex topics. These perspectives can help make object-oriented programming more accessible, even for young learners.
In object-oriented programming, inheritance is more than just copying attributes and methods. When inheritance is used solely for that purpose, it becomes abusive inheritance, and composition should be preferred instead — the well-known “has-a” relationship, versus inheritance as an “is-a” relationship. This is why the principle of composition over inheritance exists.
Clprolf secures inheritance by adding declensions and semantic checks. These ensure that inheritance carries a meaningful relationship, not just a technical one. For example, a business class cannot inherit from a computational class.
Still, role consistency is not always enough. A Human class could inherit from a Heart class — both being real-world simulations — but the relationship would remain incoherent. The nature keyword prevents such misuse by enforcing that inheritance only occurs between entities of the same kind.
In this sense, Clprolf strengthens OOP by embedding safeguards that reflect what a careful programmer would already apply as good practices.
At the same time, Clprolf preserves flexibility: developers can override these restrictions with @Forced_inh or @Forced_int_inh when practical needs demand it. This ensures that Clprolf remains as powerful as classical OOP languages, while adding semantic rigor where appropriate.
In Clprolf, the mindset is to stay as close as possible to concrete reality. This ensures that real-world use cases can always be modeled effectively.
worker_agent reminds us that, in the end, source code is compiled into low-level instructions — a technical realization of an abstract idea.Another distinctive feature of Clprolf is its focus on reasoning. Problems are treated as independent from the fact that they are implemented in software. In principle, the same reasoning could be done with a sheet of paper, without a computer at all.
Even worker_agent methods are framed as simulations of a worker — almost like a human — executing a job with specific capacities. This guarantees that Clprolf always remains simple and intuitive.
Clprolf is closer to Simula than to Smalltalk: objects are key, but method calls remain the natural way to express actions. Programmers intuitively call methods rather than send messages, which keeps an algorithmic mindset.
If Clprolf were message-based, the metaphor would be one of talking to objects rather than passing messages between them. The programmer becomes the conductor of the orchestra: objects are puppets, the programmer the puppeteer. Interfaces then become the vocabulary needed to talk with objects, which aligns with the notion of versions and capacities.
At runtime, the computer executes the method calls, and agent objects become worker_agent in a technical sense, echoing Smalltalk’s vision where objects themselves act as message senders.
Clprolf insists on keeping an algorithmic perspective, even for agent classes. Saying “object A sends a message to object B” can obscure the underlying algorithm. Instead, Clprolf frames this as the programmer writing an algorithm, implemented through method calls.
This is why Clprolf is aligned with languages like Java, C#, and PHP — not purely message-oriented, but algorithmically grounded. agent declensions are always described through algorithms that define their behavior.
Alan Kay, who coined the term object-oriented programming, described the idea as:
“The big idea was to use encapsulated mini-computers in software which communicated via message passing rather than direct data sharing.”
In Clprolf, worker_agent declensions embody this concept: they can be seen as mini-computers, encapsulated and communicating with one another.
worker_agent is like one of Kay’s mini-computers.agent and worker_agent forms a network of communicating objects.Thus, Clprolf bridges two perspectives:
agent) and computational workers (worker_agent).worker_agent, consistent with Alan Kay’s “mini-computer” metaphor.For example, a Sorter can be viewed either as an agent (a human expert at sorting) or as a worker_agent (a computer program performing the sort). In both cases, Clprolf provides a coherent interpretation, staying true to reality while remaining compatible with the historical roots of OOP.
No runtime overhead: Clprolf adds semantics and clarity on top of Java without impacting runtime performance. Object roles reduce excessive inheritance and encourage best practices, but all role-related keywords are resolved at compile time. The generated executables are effectively the same as standard Java (and the same applies to the C# and PHP frameworks).
Design leads to performance: Well-structured and well-understood systems are key to achieving efficiency. By guiding developers toward better architectures, Clprolf helps avoid misconceptions and makes it easier to identify optimizations. In this sense, Clprolf indirectly contributes to performance through design quality.
Clprolf was created to simplify the writing and understanding of object-oriented code. Its primary goal is not algorithm design. Yet, we can observe that it sometimes influences the way algorithms are written, indirectly.
underst can highlight complex or unintuitive parts of an algorithm.agent vs. worker_agent) can give different perspectives on the same algorithm, enriching the way we think about the problem.Ultimately, Clprolf influences algorithm writing by encouraging well-designed classes and methods — nothing more. This influence is indirect, but meaningful.
Like pure OOP rests on the concept of objects, Clprolf rests on declensions, which are intended to remain stable.
underst and concurrency/parallelism aids were added later, but the core principles have remained stable from the beginning.The principles of Clprolf are simple, easy to understand, and verifiable. They are constantly compared against other perspectives to ensure coherence — as shown in the reflection on messages in OOP, which found a common ground between Smalltalk, Alan Kay’s vision, and Clprolf.
Let’s compare how the Proxy pattern appears in classical OOP and in Clprolf. This is not a criticism of design patterns or of classical languages — Clprolf is itself an OO language — but a way to see how Clprolf may provide clarity and simplicity.
agent declensions, we immediately capture that the proxy is meant to carry the same meaning as the original object. A concrete example is an Image object, where the proxy adds security or deferred loading.with_compat highlights weak coupling directly in the code.In classical OOP, the Proxy pattern is remembered as proxy object + interface + real subject. But with many patterns having overlapping structures, it is easy to confuse them — even for experienced programmers. The distinction between Proxy and Adapter, for example, may seem like a minor technical detail.
Clprolf, by contrast, provides semantics that sharpen critical thinking: patterns feel more memorable, and often less necessary, because the design emerges naturally from declensions and roles.
worker_agentClprolf also allows us to ask whether the real subject is an agent or a worker_agent. If the subject is a worker_agent, we might wonder why it does not already embed the security provided by the proxy. In such cases, inheritance could often be the better choice, since the proxy and subject would naturally share methods.
This perspective is not available in classical OO languages like Java or C++, where such distinctions are absent.
With Clprolf, the Proxy pattern becomes simple enough to explain to a child: a proxy is “just another version of the same thing.” This level of clarity is hard to achieve with the classical approach, where the vocabulary of patterns can obscure the core idea.
In short, Clprolf not only makes the Proxy pattern easier to master, but also shows that, in many cases, the pattern may not even be needed: the language itself already guides the design toward the right structure.
worker_agent and agentTo illustrate, let’s implement the insertion sort algorithm in two ways:
As a worker_agent (InsertionSorterWorker):
As an agent with a HUMAN_EXPERT role (InsertionSorter):
@Underst modifier can be used for steps that appear unintuitive but are in fact necessary — for instance, shifting values from the end of the array.Both approaches produce the same result, but the perspectives differ:
worker_agent solution is closer to the machine’s mindset.agent solution reflects human reasoning, making it perhaps more intuitive for communication.Example: insertion sort with worker_agent and agent
Both examples implement the insertion sort algorithm, but with different perspectives.
package org.clprolf.examples.miscellaneous.insertionsort;
import org.clprolf.simolframework.java.Role;
import org.clprolf.simolframework.java.Worker_agent;
import org.clprolf.simolframework.java.Agent;
@Worker_agent
public class InsertionSorterWorker {
    private int array[]; 
    private int workingArray[];
    private int virtualLengthWorkingArr;
    public InsertionSorterWorker(int theArray[]) {
        this.array = theArray;
    }
    public int[] sort(){
        this.workingArray = new int[this.array.length];
        this.virtualLengthWorkingArr = 0;
        //Browse each element of the original array
        for(int i = 0;i<this.array.length;i++) {
            this.insertElement(array[i]);
        }
        return this.workingArray;
    }
    private void insertElement(int value) {
        int place;
        place = this.findInsertionIndex(value);
        this.insertAndShift(value, place);
    }
    private int findInsertionIndex(int valeur) {
        if (this.virtualLengthWorkingArr == 0) return 0;
        for(int i=0;i<this.virtualLengthWorkingArr;i++) {
            if (valeur <= this.workingArray[i]) {
                return i;
            }
        }
        return this.virtualLengthWorkingArr;
    }
    private void insertAndShift( int value, int place) {
        //I virtually enlarge my final array
        this.virtualLengthWorkingArr++;
        for (int i=this.virtualLengthWorkingArr-1;i>place;i--) {
            this.workingArray[i] = this.workingArray[i-1];
        }
        //Adding the new value.
        this.workingArray[place] = value;
    }
}
package org.clprolf.examples.miscellaneous.insertionsort;
import org.clprolf.simolframework.java.Role;
import org.clprolf.simolframework.java.Agent;
import org.clprolf.simolframework.java.Underst;
@Agent(Gender.HUMAN_EXPERT)
public class InsertionSorter {
    public int[] array;
    public int[] sortedArray;
    public int finalArrayLength;
    public InsertionSorter(int[] arrayToSort) {
        this.array = arrayToSort;
        this.sortedArray = new int[arrayToSort.length];
        this.finalArrayLength = 0;
    }
    public int[] sort() {
        //We look at each of the input values. We don't have to do it in sequence. Here, we start at the end!
        for (int i=this.array.length-1;i>=0;i--) {
            this.putInFinalArray(this.array[i]);
        }
        return this.sortedArray;
    }
    private void putInFinalArray(int valeur) {
        if (this.finalArrayLength == 0) {
            this.sortedArray[0] = valeur;
            this.finalArrayLength++;
            return;
        }
        int indice = findWhereToPut(valeur);
        //We have to resize the array, because we're going to insert
        this.finalArrayLength++;
        //
        makePlaceAtTheRight(indice);
        this.sortedArray[indice] = valeur;
    }
    // Search in a NON EMPTY array.
    // this.finalArrayLength must be > 0. Don't bother the expert for nothing.
    // Example: 2 5 7 10 => We're putting the 6 at index 2.
    // Case 2 5 7 9 => The 7 has to be in index 3, not at 2, if possible, to minimize the moves.
    private int findWhereToPut(int value) {
    //The expert may find it necessary to search by dichotomy, if he likes!
    // Here, the expert is starting from the end
        int lastPlaceIndex = this.finalArrayLength-1;
        //The expert gets rid of the case where the element is the last.
        if (this.sortedArray[lastPlaceIndex] < value) {
            return lastPlaceIndex+1;
        }
        //Now, we are sure to find. Our value is compulsorily <= all the elements.
        int indice = lastPlaceIndex;
        while (indice>=0 &&  this.sortedArray[indice] > value) indice--;
        return indice+1;
    }
    //We move all elements to the right, from the given index.
    // Don't forget that the sorted array has been enlarged.
    // Example 8/10/12, and we want to insert 9 à l'indice 1. We're moving the value at 1 to the end of the array.
    // We're starting from the end, to not crushing the values. It could first seem "@Underst",
    // but even in real-world, we have to approximatively do that.
    @Underst
    private void makePlaceAtTheRight(int index) {
        //The array has been increased
        int lastIndex = this.finalArrayLength - 1;
        //It should not be intuitive starting from the end, that's why the @Underst.
        for (int i = lastIndex-1; i>=index; i--) {
            this.sortedArray[i+1] = this.sortedArray[i];
        }
    }
}
This example demonstrates how Clprolf can be applied on top of existing Java libraries.
We implement a simple chat system between a client and a server:
NetworkTalker classes, modeled as agent declensions with the HUMAN_EXPERT role, represent the participants in the conversation. Each talker is able to remember what was said.worker_agent declensions (NetworkTalkerRealiz, ClientSideNetworkTalkerRealiz), which manage sockets and streams.SocketServerConfig class (an agent) provides a real-world configuration object with static fields.In this model:
ServerSocket can be seen as a SocketServer, delivering sockets once a connection is established.worker_agent classes interact with low-level technical details like sockets and streams.This separation simplifies the system compared to a traditional Java version: in Clprolf, the focus stays on the real-world metaphor of two people chatting, while technical socket handling is isolated in realization classes.
package org.clprolf.simple_examples.network;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import org.clprolf.simolframework.java.Worker_agent;
/**
 * clprolf simple example for network programming, here with sockets.
 * Example of a single chat between two applications, and a server waiting for a single connection.
 * 
 * v1.1    2024/02/09
 * @author Charles Koffler.
 *
 */
@Worker_agent
public class NetworkExampleServerLauncher {
    public static void main(String[] args) throws IOException {
        /* We could see the Java class ServerSocket as a server of sockets ! */
        ServerSocket socketServer = new ServerSocket(SocketServerConfig.PORT);
        System.out.println("Server started, waiting for a demand of connection");
        //The server is doing his job, he is waiting for a request of connection.
        Socket serverSocket = socketServer.accept();
        System.out.println("A connection has been established, sockets are plugged in");
        //We now need one of the talker, in this chat. Two sockets have been plugged in.
        NetworkTalker serverSideTalker = new NetworkTalker("The server", serverSocket);
        Scanner scanner = new Scanner(System.in);
        String wantedSentence;
        do {
            System.out.println("Enter a sentence, 'q' to stop");
            wantedSentence = scanner.nextLine();
            serverSideTalker.saySentence(wantedSentence);
            serverSideTalker.hearSentence();
        }while ( !wantedSentence.equals("q"));
        serverSideTalker.stopTalking();
        scanner.close();
    }
}
package org.clprolf.simple_examples.network;
import java.io.IOException;
import java.net.UnknownHostException;
import org.clprolf.simolframework.java.Worker_agent;
/**
 * The client application. They are talking together, in the two directions.
 * @author Charles Koffler
 *
 */
@Worker_agent
public class NetworkExampleClientLauncher {
    public static void main(String[] args) throws UnknownHostException, IOException {
        NetworkTalker clientTalker = new NetworkTalker("The client");
        while (!(clientTalker.hearSentence().equals("q"))) {
            clientTalker.saySentence("Well done!");
        }
        clientTalker.saySentence("Good bye!"); //Just for answer.
        clientTalker.stopTalking();
    }
}
package org.clprolf.simple_examples.network;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import org.clprolf.simolframework.java.Nature;
import org.clprolf.simolframework.java.Worker_agent;
@Worker_agent
public class ClientSideNetworkTalkerRealiz extends @Nature NetworkTalkerRealiz {
    public ClientSideNetworkTalkerRealiz(NetworkTalker theOwner) throws UnknownHostException, IOException  {
        super(theOwner);
        this.createSocket();
    }
    /**
     * A method for create a client-side socket!
     * @throws UnknownHostException
     * @throws IOException
     */
    private void createSocket() throws UnknownHostException, IOException {
        Socket clientSideSocket = new Socket(SocketServerConfig.HOST, SocketServerConfig.PORT);
        this.setSocket(clientSideSocket);
    }
}
package org.clprolf.simple_examples.network;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.clprolf.simolframework.java.Role;
import org.clprolf.simolframework.java.Agent;
import org.clprolf.simolframework.java.With_compat;
/**
 * A talker who could discuss with someone, threw a network. Here, it is seen as a human talker!
 * @author Charles Koffler
 *
 */
@Agent(Gender.HUMAN_EXPERT)
public class NetworkTalker {
    public static enum MSG_DIRECTION {
        SAID, HEARD
    }
    public static class Message {
        public String sentence;
        public MSG_DIRECTION direction;
        public Message(String theMsg, MSG_DIRECTION theDirect) {
            this.sentence = theMsg;
            this.direction = theDirect;
        }
    }
    private String name;
    private @With_compat List<Message> conversation; 
    /* Our talker has a state. He keeps his conversation. */
    public List<Message> getConversation() {
        return conversation;
    }
    public String getName() {
        return name;
    }
    //Associated realization worker.
    protected NetworkTalkerRealiz realiz;
    private void commonInits(String theName) {
        this.name = theName;
        this.conversation = new ArrayList<Message>();
    }
    /**
     * Constructor for a client-side network talker. Creates a client socket.
     * @param theName
     * @throws UnknownHostException
     * @throws IOException
     */
    public NetworkTalker(String theName) throws UnknownHostException, IOException {
        this.realiz = new ClientSideNetworkTalkerRealiz(this);
        this.commonInits(theName);
    }
    /**
     * Used for the case of a server-side socket, so it is created by the server of sockets.
     * @param theName
     * @param givenSocket
     * @throws IOException
     */
    public NetworkTalker(String theName, Socket givenSocket) throws IOException {
        this.commonInits(theName);
        this.realiz = new NetworkTalkerRealiz(this);
        this.realiz.setSocket(givenSocket);
    }
    /**
     * The talker is talking!
     * @param sentence
     */
    public void saySentence(String sentence) {
        try {
            Message msg = new Message(sentence, MSG_DIRECTION.SAID);
            this.conversation.add(msg);
            this.realiz.display("Message said: " + sentence); //This server sends lines, terminated by "\n".
            this.realiz.writeLine(sentence);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * The talker listen to a sentence from the other talker.
     * @return
     */
    public String hearSentence() {
        try {
            String sentence =  this.realiz.readLine();
            this.realiz.display("Message heard: " + sentence);
            Message msg = new Message(sentence, MSG_DIRECTION.HEARD);
            this.conversation.add(msg);
            return sentence;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    public void stopTalking() throws IOException {
        this.realiz.display("Stop talking");
        this.realiz.close();
        this.realiz.displayConversation();
    }
}
package org.clprolf.simple_examples.network;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import org.clprolf.simolframework.java.Worker_agent;
import org.clprolf.simple_examples.network.NetworkTalker.MSG_DIRECTION;
import org.clprolf.simple_examples.network.NetworkTalker.Message;
/**
 * The worker for handling computer lower level tasks, associated with a NetworkTalker!
 * @author Charles Koffler
 *
 */
@Worker_agent
public class NetworkTalkerRealiz {
    /**
     * In some cases, owner could be useful, especially to access fields to display, and this kind of stuff.
     */
    protected NetworkTalker owner;
    private Socket theSocket;
    private PrintWriter writer;
    private BufferedReader reader;
    /**
     * The socket dependency have to be injected later, with setSocket().
     * @param theOwner
     */
    public NetworkTalkerRealiz(NetworkTalker theOwner) {
        this.owner = theOwner;
    }
    /**
     * The way to inject this dependency.
     * @param socket
     * @throws IOException
     */
    public void setSocket(Socket socket) throws IOException {
        this.theSocket = socket;
        //the writer
        //First we obtain a stream. A stream could be viewed as a real-world stream.
        OutputStream theOutputStream = this.theSocket.getOutputStream();
        //A writer could be viewed as a @Simu_real_obj(Gender.HUMAN_EXPERT), a real-world writer.
        writer = new PrintWriter(theOutputStream);
        //The reader
        reader = new BufferedReader(new InputStreamReader(this.theSocket.getInputStream()));
    }
    public void writeLine(String message) throws IOException {
        writer.println(message);
        writer.flush();
    }
    public String readLine() throws IOException {
        return reader.readLine();
    }
    public void display(String theString) {
        System.out.println(this.owner.getName() + ": " + theString); //Here, an example of the need to have the owner in the technical class.
    }
    /**
     * Display the history of the conversation
     */
    public void displayConversation() {
        System.out.println("History of the conversation: ");
        System.out.println();
        for (Message currentMsg: this.owner.getConversation()) {
            System.out.println("Message: ");
            if (currentMsg.direction == MSG_DIRECTION.SAID) {
                System.out.print("Said;-");
            }
            else {
                System.out.print("Heard;-");
            }
            System.out.println(currentMsg.sentence + "-");
        }
    }
    public void close() throws IOException {
        theSocket.close();
    }
}
package org.clprolf.simple_examples.network;
import org.clprolf.simolframework.java.Abstraction;
/**
 * The configuration object of our server of sockets.
 * @author Charles Koffler
 *
 */
@Abstraction
public class SocketServerConfig {
    public static String HOST = "localhost";
    public static int PORT = 8080;
}
This annex gathers the formal components of the Clprolf specification:
the full grammar (ANTLR4) and the semantic and architectural rules (ARCH_*).
These rules define how the compiler interprets declensions, inheritance, contracts, genders, concurrency annotations, and forced exceptions. Each rule has a unique identifier for traceability and automated testing.
💡 The Annex serves as a reference for both compiler developers and framework contributors. It ensures that every semantic behavior in Clprolf can be tested, extended, and justified.
This annex contains the complete Clprolf grammar, based on Java 8 and extended with Clprolf-specific keywords and constructs.
It defines the syntax used by the compiler to recognize:
agent, worker_agent, abstraction, etc.)nature, contracts, extends)@Long_action, @One_at_a_time, etc.)📘 The grammar is written in ANTLR4 format and serves as the single source of truth for both the Clprolf compiler and any compatible parsers.
normalClassDeclaration : classModifier* 'class_for'? clprolfDeclension Identifier typeParameters? superclass? superinterfaces? classBody ;
clprolfDeclension : 'agent' | 'abstraction' | 'simu_real_obj' | 'worker_agent' | 'comp_as_worker' | 'model' | 'information' | 'indef_obj' ;
normalInterfaceDeclaration : interfaceModifier* clprolfInterfaceDeclension clprolfDeclension? Identifier typeParameters? extendsInterfaces? interfaceBody ;
clprolfInterfaceDeclension: 'compat_interf_version' | 'compat_interf_capacity' | 'compat_interf' | 'version_inh' | 'capacity_inh' ;
methodModifier : annotation | 'public' | 'protected' | 'private' | 'abstract' | 'static' | 'final' | 'synchronized' | 'native' | 'strictfp' | 'underst' | 'long_action' | 'prevent_missing_collision' | 'one_at_a_time' | 'dependent_activity' ;
fieldModifier : annotation | 'public' | 'protected' | 'private' | 'static' | 'final' | 'transient' | 'volatile' | 'with_compat' | 'turn_monitor' | 'for_every_thread' ;
extendsInterfaces : clprolfInterfExtends interfaceTypeList ;
clprolfInterfExtends : 'extends' | 'nature' ;
superclass : 'nature' classType ;
superinterfaces : 'contracts' interfaceTypeList ;
importModifier : annotation ;
importDeclaration : singleTypeImportDeclaration | singleStaticImportDeclaration ;
singleTypeImportDeclaration : importModifier 'import' clprolfInformationForJava typeName ';' ;
clprolfInformationForJava : clprolfClassInformationForJava | clprolfInterfaceInformationForJava ;
clprolfClassInformationForJava : 'java_class' clprolfDeclension ;
clprolfInterfaceInformationForJava : 'java_interface' clprolfInterfaceDeclension clprolfDeclension? ;
This annex gathers all formal semantic and architectural rules enforced (or planned) by the Clprolf compiler and framework checker.
Each rule has a unique identifier (ARCH_*) for:
💡 These rules form the semantic foundation of Clprolf — linking syntax, logic, and architecture into a unified, verifiable structure.
All Clprolf semantic rules are grouped by domain. Each prefix defines a family:
ARCH A1 (classes): Declensions must match between parent and child classes. Synonyms are considered equivalent.
ARCH A2 (classes):
For class inheritance, the nature keyword is mandatory.
ARCH A3 (classes):
No technical code is allowed inside an agent class or a system-type abstraction.
System abstractions such as Connection or Socket may only appear inside worker_agent classes,
unless explicitly forced with @Forc_pract_code on the class.
No semantic control is applied to this rule.
import java_classAll import java_class declarations must follow the same semantic rules as Clprolf class declarations.
This means that a Java class imported into Clprolf is treated as a true Clprolf class. It must declare a declension (
agent,worker_agent,model,information, orindef_obj), and may optionally declare a gender (@Expert_component,@Static, etc.).
The same architectural rules that apply to Clprolf class declarations also apply here — including inheritance consistency and gender validity.
Valid example:
@Expert_component
import java_class agent java.util.Timer;
Invalid example:
@Agent_like_advice
import java_class agent java.util.Timer;   // ❌ Advice not allowed on class imports
Semantic rule summary:
The compiler must perform the same semantic checks as for normal class declarations, raising identical errors (
ARCH_G1,ARCH_BA7, etc.) when violations occur.
ARCH BA1 (interfaces, usage):
The contracts keyword is mandatory for all implementations.
ARCH BA2 (interfaces, usage):
A class using contracts must refer to a version interface, not to a class
ARCH BA3 (interfaces, usage):
A class cannot contracts a capacity.
ARCH BA4 (interfaces, usage):
A class cannot contracts multiple version interfaces simultaneously.
ARCH BA5 (interfaces, usage):
When a class contracts a version_inh, it must have the same declension and synonym as that version_inh.
For a compat_interf_version, if a class role is defined, the implementing class must match it exactly —
reflecting a stricter compatibility contract rather than a natural hierarchy.
💡 This rule ensures structural coherence between classes and their version interfaces, whether the relationship is hierarchical (
version_inh) or strictly contractual (compat_interf_version).
ARCH BA6 — with_compat Verification
with_compat can precede a field, local variable, or parameter (fieldModifier, variableModifier),
and the compiler must verify that the unannType or catchType refers to a valid interface type.
Valid interface types include:
compat_interf, compat_interf_version, compat_interf_capacity), andjava_interface syntax.✅
with_compat java.util.List myList;✅with_compat MyCompatInterface myInterface;❌with_compat java.util.ArrayList list;
This rule ensures that with_compat always expresses a meaningful interface-level coupling,
never a dependency on an implementation class.
ARCH-BA7 (interfaces, usage):
No with_compat is allowed in method return types or in interface type lists (the list of interfaces inherited or contracted by a class or interface).
Rationale:
with_compat is reserved for variable declarations and parameters, where compatibility is actively used at runtime.
In return types or inheritance clauses, it would be meaningless because the compiler already manages structural linkage and contract declaration directly.
Scope: Applies to:
contracts),nature / extends).ARCH BA8 (interfaces, usage):
Every field or variable modifier whose unannType or catchType is a Clprolf interface must include with_compat.
ARCH BA9 — Interface Type Requirement in with_compat
Every with_compat must reference a valid interface type,
either internal (Clprolf) or external (Java).
Allowed interface types:
compat_interfcompat_interf_versioncompat_interf_capacityjava_interface✅
with_compat java.awt.event.ActionListener l;✅with_compat MyListener v;❌with_compat java.util.ArrayList list;
This ensures that all with_compat declarations refer to
pure contracts, not to executable classes.
ARCH BA10 — with_compat Extended Scope
with_compat may be used with:
compat_interf_version, compat_interf_capacity, compat_interf), andjava_interface keyword.For Clprolf types, the compiler checks the declension to ensure it is a valid compatibility interface.
For Java types, the compiler verifies only that they are declared as java_interface imports —
no further structural analysis is performed.
✅
public void setListener(with_compat java.awt.event.ActionListener l);✅public void setInterface(with_compat MyVersionInterface v);
This guarantees full semantic clarity:
Clprolf knows whether each with_compat refers to an internal or external interface,
while maintaining strict separation between both worlds.
ARCH BB1 (interfaces)
By default, a compat_interf_version cannot inherit from another compat_interf_version.
Each version defines a unique and self-contained implementation contract.
This rule ensures that “a version remains a version” — versions do not form hierarchies by nature.
However, this restriction can be explicitly relaxed when using the Features for Interface Inheritance:
@Agent, @Worker_agent, etc.),nature keyword (or @Nature annotation).This transforms the extension into a semantic inheritance rather than a simple mechanical extension, preserving meaning and consistency.
Outside of this controlled case, inheritance between versions remains forbidden,
unless explicitly forced using @Forced_int_inh.
Summary:
- ✅ Allowed: inheritance via Features for Interface Inheritance (role + nature explicitly defined).
 - ⚠️ Forbidden: direct version-to-version inheritance without features.
 - 🚫 Never implicit — must always be declared and justified.
 
ARCH BB2 (interfaces):
A capacity interface cannot inherit (nature) from a version.
capacity_inh and compat_interf_capacity are treated identically in all semantic checks.
ARCH BB3 (interfaces):
A version interface inheriting a capacity must respect the advice of that capacity in its declension.
ARCH BB4 (interfaces):
A version_inh interface must declare a declension.
A compat_interf_version may declare one.
ARCH BB5 (interfaces):
An interface that inherits must use nature if it is a version_inh or capacity_inh.
It may use extends if it is a compat_interf_version or compat_interf_capacity.
ARCH BB6 (interfaces):
Advice annotations are applied only above capacities — either version_inh or compat_interf_capacity.
They are not allowed on version interfaces or on classes.
import java_interfaceAll import java_interface declarations must follow the same semantic rules as Clprolf interface declarations.
This means that a Java interface imported into Clprolf becomes a true Clprolf interface. It must declare:
- a declension of interface (
 compat_interf_version,compat_interf_capacity, orcompat_interf),- a class role when appropriate (for
 version_inhinterfaces, such asversion_inh agent),- and an advice (
 @Agent_like_adviceor@Worker_like_advice) when it is acapacity_inhinterface.
Valid examples:
import java_interface version_inh agent java.util.List;
@Agent_like_advice
import java_interface capacity_inh java.io.Serializable;
Invalid examples:
@Static
import java_interface version_inh java.util.List;  // ❌ Gender not allowed on interfaces
import java_interface capacity_inh java.io.Serializable; // ❌ Missing advice
Semantic rule summary:
The compiler must apply the same semantic checks as for interface declarations — verifying the interface declension, the associated class role, and the presence of the proper advice for capacities.
A compat_interf_capacity declared without advice remains neutral in its definition.
However, when it is used by a version that declares a role (for example @Agent or @Worker_agent),
it is interpreted as a role-bound capacity — agent-like by default.
This interpretation does not alter the capacity itself; it only reflects how it is perceived and validated in a given context.
Summary:
- ⚪ Neutral when isolated.
 - 🟢 Interpreted as role-bound (agent-like by default) when used within a role.
 - 🧩 Context determines the semantic reading, not the declaration.
 
If a compat_interf_version without any declared declension
(agent, worker_agent, model, information, or indef_obj)
contracts a compat_interf_capacity that carries an explicit advice
(@Agent_like_advice, @Worker_like_advice, etc.),
then the compiler must raise a semantic error:
“A neutral version cannot contract a role-bound capacity. Declare a role or remove the advice from the capacity.”
Summary:
A compat_interf_version belongs by definition to the world of versions.
When it declares a class role (agent, worker_agent, model, information, or indef_obj),
it becomes semantically equivalent to a version defining features,
except for the possibility of using extends,
which reminds that it still belongs to the structural world of versions.
[Addition to ARCH_BB10] — Inheritance restriction for role-declared versions
A role-declared compat_interf_version cannot inherit (extends) another version,
since each role defines a closed world.
The only exception is the explicit use of
@Forc_int_inh, which authorizes inheritance between incompatible worlds. Theextendsclause remains syntactically allowed, but semantically valid only under this forced condition.
The annotation @Forc_inh may appear in an interface definition only when that interface defines features.
This usage corresponds to the specific case of version interfaces, where structural inheritance between worlds can be explicitly forced. In all other contexts,
@Forc_inhis forbidden.⚠️ A
compat_interf_version, whether neutral or role-declared, cannot use@Forc_inh. Versions are independent entities and cannot be chained under normal circumstances. However, in the exceptional case where acompat_interf_versionmust inherit another version, this inheritance must be explicitly forced with@Forc_int_inh, since it represents a conceptual (not structural) link.
Summary :
@Forc_inh → allowed only in interfaces with features (structural inheritance).@Forc_inh → forbidden elsewhere, including in all compat_interf_version.@Forc_int_inh → required for conceptual inheritance between versions or capacities.ARCH CA1 (genders): Declaring a gender on a class is optional. Genders are annotations that serve mainly as documentation.
ARCH CA2 (genders):
Interfaces cannot have genders — including @Static.
ARCH CA3 (genders):
No gender inheritance is checked for classes, except for static ones
(excluding abstraction, which remains neutral).
ARCH CA5 (genders):
@Active_agent is the only combinable gender.
It may only be combined with @Static, never with
@Human_expert, @Expert_component, @Human_expert_static, or @Expert_component_static.
ARCH CA6 (genders):
@Active_agent may only appear on agent declensions
(not on simu_real_obj nor on abstraction).
ARCH CA7 (genders):
@Active_agent cannot appear on a worker_agent.
ARCH CB1 (genders, static):
The three static genders (@Static, @Expert_component_static, @Human_expert_static)
are equivalent — for the compiler, they are all treated as static.
ARCH CB2 (genders, static): Static classes must contain at least one static method.
ARCH CB3 (genders, static): Static classes must contain more public static methods than non-static ones.
ARCH CB4 (genders, static):
A static class may inherit only from another static class,
and a non-static class may inherit only from a non-static class.
The opposite can be explicitly forced using @Forc_inh.
ARCH CB5 (genders, static):
Only the plain @Static gender (no expert variant) is allowed on worker_agent classes.
ARCH CB6 (genders, static):
model and information classes may contain no methods except constructors and those marked with @Forc_pract_code.
Such methods are considered small practical helpers, not domain logic.
ARCH CB7 (genders, static):
Declaring @Static is optional, but if used, the class must comply with static rules.
No compiler check enforces the presence of @Static.
ARCH DA1:
Warning if no synchronized is found in a one_at_a_time method (either on the method or inside a synchronized block).
Other synchronization mechanisms are not yet analyzed.
ARCH DA2:
Warning if a dependent_activity method is not marked as one_at_a_time.
ARCH DA3:
Warning if the number of turn_monitor fields does not match the number of one_at_a_time methods.
Only counts are compared, not pairings.
ARCH DA4:
Warning if a field marked for_every_thread lacks the volatile modifier.
ARCH DB1:
Each long_action must consist of three methods:
two public (the starter and endLongActions()), and one non-public continuation (continueActionName).
ARCH DB2:
Warning if no boolean field annotated @Long_action exists for each trio of long_action methods.
Example: six methods → two boolean fields expected.
ARCH DC1:
Warning if underst appears on a method within a worker_agent class
(indicates misplaced or non-intuitive business logic).
These rules define how forced annotations allow exceptions to normal inheritance or role constraints, while keeping the programmer’s intent explicit and traceable.
ARCH EA1:
@Forc_inh may be applied on a class or directly before the inherited type (TYPE or TYPE_USE).
ARCH EA2:
@Forc_inh allows class inheritance to be explicitly forced
—for example, an agent may inherit from a worker_agent.
ARCH EA3:
@Forc_pract_code allows small portions of worker-level code inside an agent class.
ARCH EA4:
@Forc_pract_code also allows methods inside model or information classes.
These are considered “practical helper” methods.
ARCH EA5 — Forced Inheritance from External Classes
A class inheriting from an indef_obj or from a Java class
must explicitly force this inheritance with @Forc_inh.
✅
nature @Forc_inh java.net.Socket;
The Clprolf compiler recognizes external Java classes
through java_class imports and never parses their internal structure.
This rule enforces visibility and intent when bridging domains.
ARCH EA6 — Forced Contracts with External Interfaces
A class that contracts either a compat_interf
or a Java interface imported via java_interface
must explicitly use @Forc_int_inh.
✅
contracts @Forc_inh java.util.Comparator;
This preserves explicitness in all external relationships, ensuring that no implicit compatibility contract is assumed.
ARCH EA7:
indef_obj classes may inherit from any type of interface freely, without forcing.
ARCH EB1:
@Forc_int_inh may be applied on a class, an interface, or directly before the contracted or inherited type.
If applied on a class, it affects all its contracts; if on an interface, all its inherited types.
It can also target specific types directly inside nature, extends, or contracts.
ARCH EB2:
@Forc_int_inh allows a class to contracts multiple version interfaces.
In this case, it must be declared at the class level.
ARCH EB3:
@Forc_int_inh allows a class to contracts a capacity interface.
ARCH EB4:
@Forc_int_inh allows a compat_interf_version interface to inherit from several version interfaces.
No need to use it for version_inh, which is already allowed.
It must be declared at the interface level.
ARCH EB5:
@Forc_int_inh allows a capacity interface to inherit from a version interface.
It must be declared at the interface level.
ARCH EB6:
@Forc_int_inh allows a class to implement a version_inh interface that recommends another declension.
ARCH EB7:
A static class that wants to inherit from a non-static class, or vice versa,
must force the inheritance using @Forc_inh.
ARCH EB8 — Forced Inheritance from External Interfaces
An interface that inherits from a compat_interf
or from a Java interface imported via java_interface
must use @Forc_int_inh.
✅
nature @Forc_int_inh java.util.List;
This makes the intent explicit whenever Clprolf interfaces extend interfaces defined outside the Clprolf semantic domain.
ARCH EB9:
compat_interf interfaces may inherit from any interface type without forcing.
💡 Principle — Explicit Control Over Exceptions Forced annotations never act implicitly. They always make the developer’s intent visible and deliberate. Even when forcing inheritance or mixing roles, the declared declension remains the primary semantic identity of the component.
All Java and Clprolf types must be fully qualified in import statements.
The wildcard character * is strictly forbidden.
✅
import org.clprolf.framework.java.Worker_agent;❌import org.clprolf.framework.java.*;
This rule guarantees clear dependency mapping and prevents ambiguous references.
Java types are never parsed by the Clprolf compiler.
They are treated as external entities, independent of the internal semantic engine.
Therefore, any Java version can be used for external .java files.
This preserves full interoperability between Clprolf and any Java ecosystem.
The Clprolf compiler embeds Java 8 syntax and semantics
for Java code directly written inside .clp files.
External Java code, identified by java_class or java_interface imports,
may target any later version of Java and is not parsed.
This guarantees internal stability and external flexibility.
All external Java imports must explicitly declare their nature:
import java_class fully.qualified.ClassName;
import java_interface fully.qualified.InterfaceName;
Examples:
import java_interface java.util.List;
import java_class java.util.ArrayList;
import java_interface java.awt.event.ActionListener;
This explicit typing clearly separates Clprolf symbols from Java entities and ensures that the compiler never needs to guess their origin or structure.
Every Java type used in a .clp file must be declared through a typed import
(java_class or java_interface).
If a non-typed import fails to resolve to a known Clprolf declaration, the compiler raises an ARCH-F5 error:
❌ “Unknown Clprolf type — use java_class or java_interface for external Java types.”
This rule enforces a strict semantic boundary between the Clprolf domain and the external Java domain, while keeping interoperability transparent and safe.
💎 Together, these rules (F1–F5) establish the architectural foundation of Clprolf’s clarity: every imported entity is known, named, and declared for what it is.
Clprolf does not merge with Java — it cooperates with it, through explicit, verifiable boundaries.
A Java type (java_class or java_interface) may include a semantic declaration
to define how it behaves inside Clprolf.
It may also be preceded by Clprolf annotations, such as genders or advices,
allowing the imported type to carry the same semantic richness
as a native Clprolf declaration.
From that moment, the imported element is no longer treated as a Java entity, but as a fully integrated Clprolf type, subject to all standard semantic and architectural rules.
[@ClprolfAnnotation ...]
import java_class [declension role] fully.qualified.Name;
[@ClprolfAnnotation ...]
import java_interface [declension role] fully.qualified.Name;
import java_interface version_inh abstraction java.util.List;
@Expert_component
import java_class abstraction java.net.Socket;
@Active_agent
import java_class agent java.util.Timer;
After import, these types are recognized and handled exactly like native Clprolf types, including gender and advice annotations.
| Imported type | Declension | Role | Behavior | 
|---|---|---|---|
java.util.List | 
version_inh | 
abstraction | 
Acts as a Clprolf abstraction; valid in with_compat, contracts, etc. | 
java.net.Socket | 
abstraction | 
@Expert_component | 
Treated as an expert technical abstraction, usable within worker_agents. | 
java.util.Timer | 
agent | 
@Active_agent | 
Behaves as a living agent, capable of scheduled activity. | 
This rule allows developers to map external Java types into the Clprolf ecosystem while preserving their semantics and architectural intent. Each imported type becomes a true Clprolf entity, participating in the same verification process as native classes and interfaces.
This mechanism effectively makes Java libraries appear as Clprolf-native libraries, endowed with explicit roles, genders, and advice annotations.
🧠 Clprolf does not parse Java — it interprets it. Through semantic imports, external types become part of Clprolf’s living structure.
If a Java type (java_class or java_interface) is imported
in multiple Clprolf source files with different declensions, roles, or annotations,
the compiler raises an ARCH-F7 error.
This ensures a single, coherent semantic identity for each external type.
❌ Example (error):
// In FileA.clp @Active_agent import java_class agent java.util.Timer; // In FileB.clp import java_class worker_agent java.util.Timer; // Error (ARCH-F7)Rationale: Every imported Java type must keep a unique and consistent semantic definition throughout the project. This rule guarantees architectural clarity across all source files.
💎 Together, F6 and F7 make Clprolf’s integration with Java complete: external code becomes semantically alive, unified, and verifiable.
Rule ID: ARCH-F8 Name: Coherence of Imported Java Types Scope: Java Interoperability, Import Declarations
When a java_class or java_interface is imported, its declared kind (class or interface) must remain consistent with the way it is used throughout the Clprolf source code.
False declarations — claiming that a Java class is an interface, or that a Java interface is a class — are detected by the compiler.
This verification applies automatically during the use of these imported types in:
contracts clauses,nature inheritance declarations,with_compat variable declarations.The compiler will reject incoherent usages such as:
import java_class agent java.util.List; // ❌ List is an interface in Java
public agent MyAgent contracts List;    // Detected: cannot contract a class
and also:
import java_interface version_inh worker_agent java.util.ArrayList; // ❌ ArrayList is a class
public worker_agent MyWorker nature ArrayList; // Detected: cannot inherit from an interface
Ensure that imported Java types maintain semantic coherence between their Clprolf declaration and their actual role in the language. Prevent any inconsistency in inheritance, contracts, and compatibility usage.
This rule makes false declarations detectable before code generation, ensuring that Clprolf remains logically sound and self-verifying.
ARCH-F8 — Imported Java types must keep a consistent declared kind (
java_classorjava_interface) according to their actual usage. Any false declaration will be detected during semantic validation (especially incontracts,nature, andwith_compat).
Gender annotations (@Expert_component, @Human_expert, @Static, etc.)
may be applied only to classes or to Java class imports (import java_class).
💡 This means that any gender annotation placed on an interface or on a
java_interfaceimport is semantically invalid. The compiler must raise ARCH_G1 if a gender annotation is found anywhere else.
Valid examples:
@Static
public worker_agent Launcher { }
@Expert_component
import java_class agent java.util.Timer;
Invalid examples:
@Static
import java_interface version_inh java.util.List;   // ❌ gender not allowed
@Human_expert
public version_inh agent Connection { }             // ❌ gender on an interface
Advice annotations (@Agent_like_advice, @Worker_like_advice)
may be applied only to capacity interfaces (compat_interf_capacity)
or to Java interface imports (import java_interface).
💡 This ensures that advice annotations are used exclusively in the context of capacity interfaces, either declared in Clprolf or imported from Java. The compiler must raise ARCH_G2 if an advice annotation is found on a class or on a
java_classimport.
Valid examples:
@Agent_like_advice
public compat_interf_capacity Eatable { }
@Worker_like_advice
import java_interface capacity_inh java.io.Serializable;
Invalid examples:
@Worker_like_advice
public agent Animal { }                // ❌ advice on a class
@Agent_like_advice
import java_class agent java.util.Timer; // ❌ advice on a java_class import
ARCH_G3 — Control of the @Long_action annotation
This annotation may be applied only to a field (field modifier).
Even though the annotation is technically attached to the field modifier, the compiler must still verify its proper placement.
ARCH_G4 — Control of the @Forc_pract_code annotation
This annotation may be applied only to classes.
ARCH_G5 — Control of the @Forc_inh annotation
This annotation may be applied either:
nature).ARCH_G6 — Control of the @Forc_int_inh annotation
This annotation may be applied either:
contracts).ARCH-G7 (language annotations – marker form)
Every Clprolf language annotation is a marker annotation only — it contains no attributes, parameters, or values. This differs from the framework annotations, which may define attributes or configuration metadata.
💡 Clprolf annotations express meaning, not configuration.
All Clprolf annotations are written without package names and require no imports. Only the simple name of the annotation is used.
✅ Example – valid usage:
@Expert_component
public agent Engine { }
❌ Invalid usage:
@org.clprolf.language.annotations.Expert_component   // forbidden
import org.clprolf.language.annotations.Expert_component;  // forbidden
💡 Annotations belong to the language, not to its libraries.
Within a single compilation unit, no imported type (Java or Clprolf) may share the same name as a Clprolf annotation used in that unit.
✅ Allowed:
import org.me.Static;  // OK — if @Static is not used in this file
❌ Error:
import org.me.Static;  // ❌ Conflict
@Static
public agent Service { }
💡 A file cannot import what the language already owns.
ARCH-G10 (language annotations – no source files)
Clprolf language annotations do not exist as source files. They are embedded in the compiler’s semantic layer and cannot be modified, replaced, or shadowed by user code.
💡 No source, no risk.
Language annotations are not generated in Java output. They are removed during code generation once their meaning has been processed.
✅ Example – generated Java output:
public class Engine { }
💡 What guides design disappears after doing its job.
Every Clprolf annotation has a synonym prefixed with @Clp_.
These synonyms are semantically equivalent and may be used at any time
as stylistic alternatives or to avoid conflicts.
✅ Examples:
@Clp_Static
@Clp_Expert_component
💡 Freedom without ambiguity.
No imported type may begin with the prefix Clp_
if the corresponding Clprolf annotation is used in the same compilation unit.
This ensures that the synonym namespace remains exclusive to the language.
❌ Invalid example:
import org.me.Clp_Static;   // forbidden if @Static is used
@Static
public agent Engine { }
ARCH-G14 (language annotations – categories and roles)
Clprolf language annotations belong to four categories: Genders, Advices, Forcing, and Special. Each serves a distinct semantic purpose within the language.
Genders refine the interpretation of agents.
They are always optional, including @Static.
Examples: @Expert_component, @Human_expert, @Static.
Advices define guidance for capacity interfaces.
The default advice is @Agent_like_advice.
Forcing annotations exist for special cases where an interface or capacity must explicitly enforce a constraint. They are rarely required and should be used only in specific capacity interface scenarios.
Special annotations introduce optional semantic hints,
such as @Long_action, which signals a boolean property or
extended behavior without altering structure.
💡 Genders add nuance, advices define direction, forcing ensures precision, and special annotations mark exceptions.
✅ This annex now defines the full set of semantic and architectural rules used by the Clprolf compiler and framework checker. It ensures that every exception, inheritance, or structural decision in Clprolf is explicit, justified, and traceable.
Clprolf defines a minimal set of 34 keywords. They are divided into two groups:
This structure makes Clprolf both minimal and flexible: easy to learn and memorize, yet expressive enough to capture complex system designs.
agentabstractionsimu_real_objworker_agentcomp_as_workermodelinformationindef_objcompat_interf_versionversion_inhcompat_interf_capacitycapacity_inhcompat_interfjava_class — declares that an imported type is a Java classjava_interface — declares that an imported type is a Java interfaceThese two keywords allow semantic integration of Java types inside Clprolf import declarations and enable full verification of interoperability.
understone_at_a_timedependent_activitylong_actionwith_compatturn_monitorfor_every_thread@Human_expert@Expert_component@Active_agent@Static@Human_expert_static@Expert_component_static@Agent_like_advice@Worker_like_advice@Forc_pract_code@Forc_inh@Forc_int_inh@Long_action✅ Total: 34 keywords
This annex completes the formal specification of Clprolf. It connects grammar, semantics, and keywords into a single consistent vision — turning clarity from philosophy into verifiable structure.