FuzzyLang is a custom programming language designed to define and execute classes, methods, and fuzzy operations in a flexible and extensible way. It provides a dynamic environment where classes and methods can be created and invoked, and variables can be managed across different scopes. With support for partial evaluation, inheritance, nested classes, and fuzzy operations such as addition, multiplication, and conditional statements, FuzzyLang is designed for efficient and adaptable execution.
sbt compile
sbt run
sbt test
- Class Definitions: Create and manage classes with support for defining variables, methods, and nested classes.
- Inheritance: Classes can inherit from other classes, inheriting methods and variables from the superclass.
- Method Invocation: Methods can be defined and invoked with parameters, with the flexibility to resolve variables dynamically.
- Fuzzy Operations: Supports a variety of operations, such as addition (
ADD), multiplication (MULT), and comparisons (GREATER,LESS), that operate on fuzzy values like numbers or variables. - Partial Evaluation: FuzzyLang performs partial evaluation on expressions, simplifying them as much as possible before execution.
If an expression cannot be fully evaluated due to missing variables (e.g., if a variable is undefined),
the expression is partially evaluated and stored as a deferred action. When the missing variable is later assigned a value (e.g., using
Assign), the partially evaluated expression is reevaluated automatically, allowing the language to update and execute the expression with the new value. This ensures that expressions remain dynamic and flexible, only fully executing when all necessary values are available.
FuzzyLang uses a dynamic but structured typing system:
- FuzzyOperations: The primary type in FuzzyLang is
Double, which is used by built-in operations. Every operation on fuzzy values evaluates to aDouble. - User-Defined Types: When you define a class via
DefClass, it creates a new user-defined type. However, the variables inside these classes still storeFuzzyOperations(i.e.,Doublevalues). This means the internal computation remains consistent, while you gain abstraction and structure with classes. - Type Safety: Type safety is ensured at runtime by restricting operations to compatible types. For instance, attempting to perform
ADDbetween a class instance and aDoublewill trigger a runtime check, preventing invalid operations.
In short: user-defined classes provide type structure and organization, but all values stored and computed remain fuzzy numeric values (
Double).
FuzzyLang supports the following operations for building expressions:
- Arithmetic:
ADD,MULT - Logical:
AND,OR,XOR,NOT,NAND - Value and Variables:
Value(Double)– wraps a constant numberVariable(String)– references a variable by name
These can be freely composed to form expressions, supporting partial evaluation and dynamic execution.
One of the standout features of FuzzyLang is its partial evaluation mechanism.
This feature evaluates expressions as much as possible, simplifying them before execution.
For example, in constructs like IFTRUE, the condition is evaluated partially if some values are unknown.
-
If the condition cannot be fully evaluated due to missing values, FuzzyLang will partially evaluate both branches of the
IFTRUEconstruct (THENEXECUTEandELSERUN), simplifying the expressions within them. This allows for deferred execution, meaning that the condition is re-evaluated only once all required values are available. -
Once the condition can be fully evaluated, FuzzyLang knows which branch to execute, making the flow of execution dynamic and efficient.
This approach ensures that expressions are evaluated only when all necessary information is available, improving performance and making the language more flexible when dealing with incomplete or deferred data.
// Define a class named Base and a class method baseMethod which adds variable x and y
DefClass("Base")
DefMethod(Class("Base"), "baseMethod", ADD(Variable("x"), Variable("y")))
IFTRUE(GREATER(ADD(Value(0.1), Variable("x")), MULT(Value(0.7), Value(0.7))), THENEXECUTE {
val baseInstance = CreateClass(Class("Base"))
val baseMethodResult = baseInstance.invokeMethod("baseMethod", List(DoubleArg("y", Value(0.2))))
Assign("z", baseMethodResult)
}, ELSERUN {
Assign("z", Value(0.3))
})
// Assign the variable x with value 0.8
Assign("x", Value(0.8))
// (0.1 + 0.8) > (0.7 * 0.7)
// THENEXECUTE will execute and z will be assigned (0.8 + 0.2) => z = 1.0- In this example, the condition
(GREATER(ADD(Value(0.1), Variable("x")), MULT(Value(0.7), Value(0.7))))is partially evaluated because the value ofxis unknown. Both branches (THENEXECUTEandELSERUN) are partially evaluated, and once the value ofxis assigned, the condition is re-evaluated to determine which branch to execute.