Manuale di riferimento MALDA™

Il linguaggio di programmazione AI-First - Versione 1.0.11

1. Introduzione

1.1 Panoramica

MALDA: The AI-First Programming Language è un linguaggio di programmazione moderno e orientato agli oggetti, pensato per costruire agenti AI e workflow di automazione. Con supporto nativo all'integrazione LLM, all'orchestrazione di agenti e ai sistemi multi-agente, MALDA rende semplice creare applicazioni intelligenti e autonome.

Il linguaggio ha una sintassi pulita e leggibile, le strutture di controllo essenziali, capacità di I/O built-in e pieno supporto alla programmazione orientata agli oggetti: classi, ereditarietà e polimorfismo. Ciò che distingue MALDA sono le capacità AI di prima classe - classi built-in per client LLM, conversazioni, agenti e tool, con cui si costruiscono applicazioni AI sofisticate con poco codice.

L'intestazione della pagina riporta la versione della toolchain distribuita (lo stesso numero della CLI). La semantica del linguaggio core è specificata in malda-language-1.0.

Come affrontare MALDA: se programmi già, parti da Indice → First Look (prompt + schema + validate, senza API key). Se stai imparando a programmare, impara prima il linguaggio core: io.print, variabili, input, condizionali, cicli e funzioni. Dopo il percorso core, diramati verso Testing e qualità, Dati e database e App nel browser. Entrambi i percorsi arrivano allo stesso runtime AI-first.

Che cosa significa MALDA?

MALDA: Multi Agent Language with Development Automation - Il nome MALDA riflette i principi e la filosofia di progettazione del linguaggio:

Il runtime unificato che rende possibile tutto questo è descritto di seguito.

1.2 Architettura AI Unified Runtime

MALDA poggia sull'AI Unified Runtime Architecture - un sistema unificato in cui il runtime del linguaggio, le capacità AI, il framework degli agenti, l'ecosistema di tool e il deployment sono integrati in un'unica architettura coerente. A differenza degli approcci tradizionali che combinano librerie e framework separati, MALDA offre un runtime unificato in cui tutto collabora senza interruzioni.

Che cos'è l'AI Unified Runtime Architecture?

AI Unified Runtime Architecture significa che le capacità AI non sono aggiunte come librerie o framework esterni, ma sono costruite direttamente nel runtime del linguaggio. Ne risulta un sistema unificato in cui:

Approccio tradizionale e runtime unificato

Negli approcci tradizionali, costruire applicazioni AI richiede di combinare più componenti separati:

Questo introduce overhead dalle chiamate di libreria, serializzazione tra i componenti e requisiti di setup complessi.

Con l'AI Unified Runtime Architecture tutti questi componenti sono integrati in un unico runtime:

Componenti core

Runtime unificato del linguaggio

L'interprete include le capacità AI come funzionalità di prima classe. Classi come LLMClient, Agent e Conversation sono built-in nel linguaggio, non importate da librerie esterne.

Layer AI Runtime integrato

Le operazioni AI si eseguono nello stesso runtime del codice ordinario. Questo offre:

Runtime unificato di orchestrazione degli agenti

Più agenti girano nello stesso processo e possono:

Runtime unificato dell'ecosistema di tool

I tool sono integrati nel runtime:

Runtime unificato di deployment

Il compilatore incorpora il runtime MALDA e le capacità AI in eseguibili standalone:

Vantaggi

Come MALDA la implementa

L'implementazione MALDA dell'AI Unified Runtime Architecture è composta da quattro layer:

Questa architettura rende MALDA davvero "AI-first": non un linguaggio con funzionalità AI aggiunte, ma un linguaggio in cui l'AI è fondamentale per l'architettura del runtime stesso.

1.3 Funzionalità del linguaggio

Capacità del linguaggio core

MALDA include:

Funzionalità del linguaggio core

Funzionalità core AI-First

⚠️ Importante: i sistemi di agenti autonomi con accesso ai tool comportano rischi significativi di sicurezza e operativi. Vedi 18. Orchestrazione di agenti per un disclaimer dettagliato e le strategie di mitigazione del rischio prima di distribuire agenti in produzione.

Funzionalità Web e API

1.4 Ambienti di sviluppo

Desktop IDE WPF

1.5 Compilatore

Il compilatore MALDA supporta la compilazione in due modalità:

Entrambe le modalità producono file .exe standalone con il runtime MALDA incorporato. Alcune dipendenze esterne (es. librerie client SQL Server/PostgreSQL, DLL native LLamaSharp) possono richiedere DLL aggiuntive accanto all'eseguibile.

1.6 Composizione del sorgente: include, using, import, export

MALDA ha tre modi per portare codice da altrove, e uno per controllare cosa un file offre agli altri. Tutti e quattro sono solo a top-level.

FormaCosa fa
include "path/file.malda";Compone il sorgente: carica e fa il parse di un altro file MALDA nel programma corrente, come se il suo testo ne facesse parte.
using PackageName;Carica un modulo di pacchetto installato e unisce i suoi simboli esportati nello scope corrente.
import "path/file.malda";Carica un file locale come modulo e unisce solo i suoi simboli esportati.
import { a, b } from "path/file.malda";Stesso caricamento, ma unisce solo gli export nominati nello scope corrente.
import alias = ...;Come sopra, ma lega i simboli esportati a un unico oggetto namespace invece che allo scope corrente.
export function/class/var/type/schemaMarca una dichiarazione come parte della superficie pubblica di questo file.

Quando usare ciascuno

export e la superficie di default

export può prefissare una dichiarazione di funzione, classe, var, type o schema:

// math_utils.malda
export function add(a, b) {
    return a + b;
}

export var VERSION = "1.0";
export type Result = Ok(value) | Err(msg);
export schema Contact { name: string; }

function internalHelper(x) {   // not exported
    return x * 2;
}
Default importante: l'elenco degli export viene applicato solo quando un file contiene almeno un export. Un modulo senza alcun export pubblica ogni simbolo top-level (inclusi type / schema). Aggiungere il primo export a un file esistente quindi nasconde tutto ciò che non hai marcato — usa export type / export schema quando il modulo esporta già dei valori.

Import nello scope corrente o dietro un namespace

Senza alias, i simboli esportati vengono uniti nello scope corrente. Un nome che esiste già non viene sovrascritto, quindi il file che importa vince sempre in caso di collisione:

import "shared/math_utils.malda";

print(add(2, 3));      // 5
print(VERSION);        // "1.0"
// internalHelper(2);  // not available: never exported

L'import selettivo estrae un sottoinsieme di quella superficie (i nomi mancanti o non esportati sono errori). Golden offline: Examples/Modules/selective_import.malda, Examples/Modules/export_type_schema.malda — vedi anche docs/selective-imports.md.

import { add, VERSION } from "shared/math_utils.malda";

print(add(2, 3));
print(VERSION);
// unused();           // not imported, even if exported by the module

import { Result, Contact } from "types_lib.malda";
var r = Ok(42);                 // constructors arrive with export type Result
var ok = validate("Contact", dict { "name": "Ada" });

Con un alias, gli stessi simboli sono raggruppati in un oggetto, il che evita del tutto le collisioni:

import mathUtils = "shared/math_utils.malda";

print(mathUtils.add(2, 3));   // 5
print(mathUtils.VERSION);     // "1.0"

Le stesse due forme valgono per i pacchetti, con un nome di pacchetto puntato al posto del path stringa:

import App.Core;
import UI = App.Web.Components;

I nomi di pacchetto che iniziano con System, Microsoft o Windows vengono risolti come namespace .NET attraverso il layer di interop, non dal gestore di pacchetti. Vedi 30. Interop .NET.

Se non si riesce a risolvere un target è un errore a runtime: Package or module not found: Name per i pacchetti, e il messaggio di file-not-found sottostante per gli import di file.

Path e comportamento di sicurezza per include

Nel Desktop IDE i tab virtuali non sostituiscono include: sono una vista dell'editor su un unico file fisico. Vengono creati solo quando il sorgente contiene i separatori espliciti // @malda-section Name. La risoluzione degli include resta basata sui file e funziona come prima.

// Local file composition: everything from these files becomes part of this program
include "shared/math_utils.malda";
include "features/orders.malda";

// Package import into the current scope
using App.Core;

// Package import behind a namespace object
using UI = App.Web.Components;

1.7 Esempio rapido

Prima i costrutti caratteristici (stesso programma di Examples/Basics/first_look.malda). -> Review lega il prompt allo schema. Senza await, la chiamata è un template reso — nessuna API key. validate("Review", …) è lo stesso controllo che await eseguirebbe sul JSON del modello.

schema Review {
    summary: string;
    issues: string[];
}

prompt codeReview(code, language) -> Review {
    system: "You are an expert reviewer of {language}.",
    user: "Review this {language} code:\n\n{code}"
}

var rendered = codeReview("function add(a, b) { return a + b; }", "javascript");
io.print(rendered.user);

var checked = validate("Review", {
    "summary": "Looks fine",
    "issues": []
});
if (checked.ok) {
    io.print("schema ok: " + checked.data.summary);
}

La sintassi core usa le stesse istruzioni. Preferisci le chiamate namespaced (io.print); il print piatto continua a funzionare. I/O di file, path e ambiente: 12. Input/Output.

io.print("Hello, World!");

var name = "Alice";
var age = 25;
var pi = 3.14159;
var isActive = true;

var numbers = [1, 2, 3, 4, 5];
numbers.append(6);

function greet(name) {
    return "Hello, " + name + "!";
}

io.print(greet("Bob"));

class Person {
    public var name;
    public var age;
    
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    public function introduce() {
        io.print($"Hi, I'm {this.name} and I'm {this.age} years old.");
    }
}

var person = new Person("Charlie", 30);
person.introduce();

Vedi anche