Universal Absorption Tutorial

Learn how to absorb external code into Grey

Advanced Time: 45 minutes

Introduction

Welcome to the Universal Absorption tutorial! This advanced guide will teach you how to use one of GreyOS's most powerful features: the ability to absorb and transform code from other languages into optimized Grey code using Recursive Symbolic Execution (RSE).

Universal Absorption allows you to:

  • Convert existing JavaScript, Python, HTML, CSS, and WebAssembly to Grey
  • Integrate third-party libraries and applications into your Grey projects
  • Achieve significant performance improvements through symbolic optimization
  • Create unified applications that combine code from different sources

Note: Universal Absorption is an advanced feature that leverages GreyOS's symbolic execution engine to translate and optimize code across language boundaries.

Prerequisites

Before you begin this tutorial, make sure you have:

  • Completed the Hello World Tutorial and UI Basics Tutorial
  • Intermediate understanding of Grey programming concepts
  • Basic familiarity with at least one other programming language (JavaScript, Python, etc.)
  • GreyOS installed with the Universal Absorber module

To check if your GreyOS installation includes the Universal Absorber, run this command in the Grey Shell:

grey module list | grep absorber

If it's not installed, you can add it with:

grey module install universal-absorber

Understanding Universal Absorption

Universal Absorption is built on the principle of Recursive Symbolic Execution (RSE), which allows GreyOS to understand the meaning of code rather than just its syntax. Here's how it works:

Source Code
(JS, Python, etc.)
Symbolic Representation
(Abstract Syntax Tree)
Grey Code
(Optimized)

The absorption process involves three main stages:

  1. Parsing: The source code is parsed into a language-specific abstract syntax tree (AST)
  2. Symbolic Translation: The AST is converted to Grey's universal symbolic representation
  3. Optimization: The symbolic representation is optimized using Grey's RSE engine

Important: Not all code constructs have direct equivalents in Grey. The absorber will generate the closest semantic match and include compatibility layers when necessary.

Step 1: Absorbing JavaScript

Let's start by absorbing a simple JavaScript function. Create a file named fibonacci.js with the following content:

// JavaScript implementation of Fibonacci
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// Calculate and print Fibonacci numbers
for (let i = 0; i < 10; i++) {
    console.log(`Fibonacci(${i}) = ${fibonacci(i)}`);
}

Now, let's absorb this JavaScript code into Grey using the Universal Absorber CLI:

grey absorb js fibonacci.js --output fibonacci.grey

This command will generate a fibonacci.grey file with the absorbed code. Let's examine the result:

// Absorbed from JavaScript using Universal Absorber
// Original source: fibonacci.js

symbolic Math {
    // Fibonacci function with symbolic optimization
    function fibonacci(n: Int) -> Int {
        // Grey's symbolic engine detects recursive pattern
        // and applies memoization automatically
        if (n <= 1) {
            return n;
        }
        
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

symbolic Main {
    function run() -> Void {
        // Loop converted to Grey's range-based iteration
        for i in range(0, 10) {
            // Console.log mapped to Grey's print function
            print("Fibonacci(" + i + ") = " + Math.fibonacci(i));
        }
    }
}

// Entry point
entry(Main.run);

You can run the absorbed Grey code with:

grey run fibonacci.grey

Notice how the Universal Absorber made several optimizations:

  • Organized code into symbolic structures
  • Added type annotations (Int)
  • Automatically applied memoization to the recursive function
  • Converted JavaScript's for loop to Grey's range-based iteration
  • Mapped console.log to Grey's print function

Step 2: Absorbing Python

Now let's try absorbing a Python script. Create a file named data_processor.py with the following content:

#!/usr/bin/env python3
# Python data processor example

class DataProcessor:
    def __init__(self, data):
        self.data = data
        self.results = {}
    
    def process(self):
        # Calculate statistics
        self.results['sum'] = sum(self.data)
        self.results['avg'] = sum(self.data) / len(self.data)
        self.results['min'] = min(self.data)
        self.results['max'] = max(self.data)
        return self.results
    
    def print_results(self):
        print("Data Analysis Results:")
        for key, value in self.results.items():
            print(f"{key.capitalize()}: {value}")

# Sample data
sample_data = [12, 45, 33, 27, 89, 54, 18, 76]

# Process and print results
processor = DataProcessor(sample_data)
processor.process()
processor.print_results()

Now, absorb the Python code into Grey:

grey absorb python data_processor.py --output data_processor.grey

Let's examine the absorbed Grey code:

// Absorbed from Python using Universal Absorber
// Original source: data_processor.py

symbolic DataProcessor {
    // Properties
    data: List;
    results: Map;
    
    // Constructor equivalent
    function init(data: List) -> DataProcessor {
        let processor = DataProcessor {
            data: data,
            results: {}
        };
        return processor;
    }
    
    // Process method with Grey optimizations
    function process(self) -> Map {
        // Grey's symbolic execution optimizes these calculations
        // by recognizing common patterns and avoiding redundant computations
        let sum_value = self.data.reduce((a, b) => a + b, 0);
        
        self.results["sum"] = sum_value;
        self.results["avg"] = sum_value / self.data.length();
        self.results["min"] = self.data.min();
        self.results["max"] = self.data.max();
        
        return self.results;
    }
    
    function printResults(self) -> Void {
        print("Data Analysis Results:");
        
        // Iterate over map entries
        for (key, value) in self.results {
            // String interpolation converted to Grey's format
            print(key.capitalize() + ": " + value);
        }
    }
}

symbolic Main {
    function run() -> Void {
        // Sample data
        let sampleData = [12, 45, 33, 27, 89, 54, 18, 76];
        
        // Create processor instance
        let processor = DataProcessor.init(sampleData);
        
        // Process and print results
        processor.process();
        processor.printResults();
    }
}

// Entry point
entry(Main.run);

You can run the absorbed Grey code with:

grey run data_processor.grey

Notice the transformations applied to the Python code:

  • Converted Python class to Grey symbolic structure
  • Transformed Python's __init__ method to a factory function
  • Added static type annotations (List, Map)
  • Optimized calculations by identifying common sub-expressions
  • Transformed Python's dictionary iteration to Grey's for-in loop

Step 3: Absorbing Web Applications

The Universal Absorber can also convert entire web applications (HTML, CSS, and JavaScript) into Grey. Let's create a simple web calculator:

First, create an app directory and add these files:

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Calculator</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="calculator">
        <div class="display" id="display">0</div>
        <div class="buttons">
            <button onclick="clearDisplay()">C</button>
            <button onclick="appendToDisplay('7')">7</button>
            <button onclick="appendToDisplay('8')">8</button>
            <button onclick="appendToDisplay('9')">9</button>
            <button onclick="appendToDisplay('/')">/</button>
            <button onclick="appendToDisplay('4')">4</button>
            <button onclick="appendToDisplay('5')">5</button>
            <button onclick="appendToDisplay('6')">6</button>
            <button onclick="appendToDisplay('*')">*</button>
            <button onclick="appendToDisplay('1')">1</button>
            <button onclick="appendToDisplay('2')">2</button>
            <button onclick="appendToDisplay('3')">3</button>
            <button onclick="appendToDisplay('-')">-</button>
            <button onclick="appendToDisplay('0')">0</button>
            <button onclick="appendToDisplay('.')">.</button>
            <button onclick="calculate()">=</button>
            <button onclick="appendToDisplay('+')">+</button>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

style.css:

body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    margin: 0;
}

.calculator {
    background-color: #333;
    border-radius: 10px;
    padding: 20px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

.display {
    background-color: #222;
    color: white;
    font-size: 2rem;
    padding: 10px;
    text-align: right;
    margin-bottom: 20px;
    border-radius: 5px;
    min-height: 40px;
}

.buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
}

button {
    background-color: #444;
    color: white;
    border: none;
    padding: 15px;
    font-size: 1.2rem;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #555;
}

button:active {
    background-color: #666;
}

script.js:

let displayValue = '0';

function updateDisplay() {
    document.getElementById('display').textContent = displayValue;
}

function appendToDisplay(value) {
    if (displayValue === '0') {
        displayValue = value;
    } else {
        displayValue += value;
    }
    updateDisplay();
}

function clearDisplay() {
    displayValue = '0';
    updateDisplay();
}

function calculate() {
    try {
        // Using Function constructor for evaluation (safer than eval)
        displayValue = String(new Function('return ' + displayValue)());
        updateDisplay();
    } catch (error) {
        displayValue = 'Error';
        updateDisplay();
    }
}

Now, absorb the entire web application into Grey:

grey absorb web app --output calculator_app.grey

The absorbed code will be a complete Grey application. Here's a simplified version of what it might look like:

// Absorbed web application using Universal Absorber
// Original source: app/index.html, app/style.css, app/script.js

import { UI } from "greyos.ui";
import { App } from "greyos.app";

symbolic CalculatorApp {
    // State
    state: {
        displayValue: "0"
    },
    
    // Methods
    updateDisplay: function() -> Void {
        this.components.display.update({ 
            content: this.state.displayValue 
        });
    },
    
    appendToDisplay: function(value: String) -> Void {
        if (this.state.displayValue === "0") {
            this.state.displayValue = value;
        } else {
            this.state.displayValue += value;
        }
        this.updateDisplay();
    },
    
    clearDisplay: function() -> Void {
        this.state.displayValue = "0";
        this.updateDisplay();
    },
    
    calculate: function() -> Void {
        try {
            // Symbolic execution converts JavaScript's dynamic evaluation
            // to Grey's safer expression evaluation
            this.state.displayValue = String(
                GreyMath.evaluateExpression(this.state.displayValue)
            );
            this.updateDisplay();
        } catch (error) {
            this.state.displayValue = "Error";
            this.updateDisplay();
        }
    },
    
    // Components (absorbed from HTML/CSS)
    components: {
        calculator: UI.Container {
            style: {
                background: "#333",
                borderRadius: "10px",
                padding: "20px",
                boxShadow: "0 5px 15px rgba(0, 0, 0, 0.2)"
            },
            children: [
                UI.Container {
                    id: "display",
                    content: "0",
                    style: {
                        background: "#222",
                        color: "white",
                        fontSize: "2rem",
                        padding: "10px",
                        textAlign: "right",
                        marginBottom: "20px",
                        borderRadius: "5px",
                        minHeight: "40px"
                    }
                },
                UI.Grid {
                    columns: 4,
                    gap: "10px",
                    children: [
                        UI.Button {
                            text: "C",
                            onClick: function() { CalculatorApp.clearDisplay(); },
                            style: { background: "#444", color: "white" }
                        },
                        UI.Button {
                            text: "7",
                            onClick: function() { CalculatorApp.appendToDisplay("7"); },
                            style: { background: "#444", color: "white" }
                        },
                        // Other buttons omitted for brevity...
                        UI.Button {
                            text: "=",
                            onClick: function() { CalculatorApp.calculate(); },
                            style: { background: "#444", color: "white" }
                        }
                    ]
                }
            ]
        }
    },
    
    // Initialize and return the main component
    initialize: function() -> UI.Component {
        return this.components.calculator;
    }
}

// Entry point
App.render(CalculatorApp.initialize());

You can run the absorbed Grey calculator app with:

grey run calculator_app.grey

The Universal Absorber has performed several transformations:

  • Combined HTML, CSS, and JavaScript into a single Grey application
  • Converted the DOM structure to Grey's UI component hierarchy
  • Transformed CSS styles into component style properties
  • Converted event handlers to Grey's event system
  • Replaced unsafe evaluation with Grey's secure expression evaluator

Step 4: Performance Analysis

One of the key benefits of Universal Absorption is the automatic performance optimization. Let's analyze the performance difference between the original code and the absorbed Grey code.

We can use Grey's benchmarking tools to compare the performance:

grey benchmark compare fibonacci.js fibonacci.grey

This will output performance metrics like execution time, memory usage, and CPU utilization. Typically, you'll see significant improvements in the Grey version due to:

Optimization Type Original Code Grey Code
Memoization Manual implementation Automatic
Type Optimization Dynamic typing Static type inference
Memory Management Garbage collection Reference counting & pooling
Symbolic Folding None Automatic expression simplification
Parallelization Manual thread management Automatic task parallelization

Tip: The Universal Absorber excels at optimizing mathematical and recursive algorithms, often achieving 2-10x performance improvements without any manual intervention.

Next Steps

Congratulations! You've learned how to use the Universal Absorber to convert code from other languages into optimized Grey code. Here are some suggestions for continuing your journey:

  • Try absorbing more complex applications and libraries
  • Experiment with absorbing WebAssembly modules using grey absorb wasm file.wasm
  • Learn how to customize the absorption process with transformation rules
  • Explore the WASM Integration Tutorial to learn how to directly interact with WebAssembly modules

Advanced tip: For large projects, use the --profile flag to generate a detailed absorption report that highlights optimization opportunities and potential issues.