Umka: Neue statisch typisierte Skriptsprache


Die erste Version der statisch typisierten einbettbaren Skriptsprache Umka , die ich entwickelt habe, wurde gerade veröffentlicht . Ziel ist es, die Flexibilität bekannter Skriptsprachen mit dem Schutz vor Typfehlern bei der Kompilierung in Bytecode zu kombinieren. Die Hauptidee der Sprache - Explizit ist besser als implizit - ist aus "Zen of Python" entlehnt, sollte hier jedoch eine etwas andere und offensichtlichere Bedeutung erhalten.

Egal wie privat und subjektiv die Eindrücke waren, die mich dazu veranlassten, die Entwicklung der Sprache zu übernehmen, ich hoffe, dass der Plan nicht naiv war. Unter dem Schnitt werde ich kurz über die Fähigkeiten der Sprache und die Motive für ihre Entstehung sprechen.

Motive


Die erste Tugend der dynamischen Typisierung wird normalerweise als Verkürzung des Entwicklungs- / Debugging-Zyklus und Einsparung von Programmierzeit bezeichnet. Ich muss zugeben, dass meine eigenen Erfahrungen dies in keiner Weise bestätigen, da die Gefahr besteht, dass die Öffentlichkeit unzufrieden wird. Jedes Mal, wenn ich mein Trainingsskript für neuronale Netze in Python geringfügig korrigiert habe, muss ich warten, bis Python, NumPy und PyTorch geladen sind, eine große Anzahl von Daten aus Dateien lesen, auf die GPU übertragen, mit der Verarbeitung beginnen - und erst dann feststellen, dass PyTorch einen Größentensor erwartet (1, 1) , m, n, 3) anstelle von (1, m, n, 3).

Ich gebe gerne zu, dass viele Menschen aus persönlichen Gründen dynamisch getippte Sprachen bevorzugen. Es ist sogar möglich, dass die Tendenz oder Feindseligkeit zur dynamischen Typisierung ein Phänomen in der gleichen Größenordnung ist wie die Einstellung zu Oliven und Tomatensaft. Versuche einer objektiven Untersuchung dieses Themas führen offenbar zu nicht schlüssigen Ergebnissen .

Gleichzeitig lassen die Popularität von TypeScript, die Einführung von Typanmerkungen in Python, hitzige Diskussionen über Reddit und Habré den Eindruck entstehen, dass die tatsächliche Identifizierung von Skriptsprachen mit dynamisch typisierten Sprachen überhaupt kein Dogma ist, sondern ein Zufall, und eine statisch typisierte Skriptsprache hat jedes Recht zu existieren.

Es gab also eine Sprache, die nach einer Katze benannt war, die nach einem Bären benannt war.

Zunge


Die Syntax der gesamten Sprache wurde von Go inspiriert. Beispiele für Syntaxkonstrukte finden Sie auf der Projektseite . Bei der Deklaration von Variablen kann eine Abkürzung mit Typinferenz verwendet werden. Bemerkenswert ist die Abweichung von den Go-Regeln, die in der Syntax von Zeigern festgelegt wurden. Die Macher von Go beklagten sich darüber, dass sich das wörtliche Befolgen von Beispiel C als unnötige Komplikation der Syntax herausstellte und dass es sinnvoller wäre, p^stattdessen einen Postfix-Dereferenzierungsoperator wie Pascal einzuführen *p. Genau das hat Umka getan.

ÜbersetzerUmka kompiliert in Bytecode, der dann von der virtuellen Stapelmaschine ausgeführt wird. Alle Typprüfungen werden in der Kompilierungsphase durchgeführt. Die Daten auf dem Stapel enthalten keine Typinformationen mehr. Der Übersetzer wird in Form einer dynamischen Bibliothek mit eigener API und einem kleinen "Wrapper" - einer ausführbaren Datei - geliefert. Der Quellcode ist in C99 geschrieben und auf verschiedene Plattformen portiert. Builds für den x86-64-Prozessor (Windows und Linux) sind jetzt verfügbar .

Speicherverwaltungbisher auf Basis von Referenzzählern durchgeführt. Wenn die Sprache Interesse weckt und versucht wird, sie zu verwenden, ist es sinnvoll, einen fortgeschritteneren Garbage Collector einzurichten. Die Sprache unterstützt die klassischen zusammengesetzten Datentypen (Arrays und Strukturen), die auf dem Stapel platziert sind, und die dynamischen Arrays, die auf dem Heap platziert sind. Jedes klassische Array oder jede klassische Struktur kann auch mit einem expliziten Aufruf auf dem Heap platziert werden new().

Polymorphismus wird durch Schnittstellen im Go-Stil bereitgestellt. Es gibt keine Konzepte für Klasse, Objekt und Vererbung.

MultitaskingEs basiert auf dem Konzept der „Fasern“ - vereinfachte Abläufe, die innerhalb derselben virtuellen Maschine gestartet werden und sich eindeutig gegenseitig verursachen. Im Wesentlichen ist dies gleichbedeutend mit Coroutinen. Da die Logik der Verwendung dieser Coroutinen geringfügig von der Go-Tradition abweicht und sich Lua und Wren nähert, ist es sinnvoll, ein Codebeispiel anzugeben:

fn childFunc(parent: std.Fiber, buf: ^int) {
    for i := 0; i < 5; i++ {
        std.println("Child : i=" + std.itoa(i) + " buf=" + std.itoa(buf^))
        buf^ = i * 3
        fibercall(parent)
    }
}

fn parentFunc() {
    a := 0
    child := fiberspawn(childFunc, &a)    
    for i := 0; i < 10; i++ {
        std.println("Parent: i=" + std.itoa(i) + " buf=" + std.itoa(a))
        a = i * 7
        if fiberalive(child) {
            fibercall(child)
        }
    }    
    fiberfree(child)
}

Beispiele


Als grundlegendes Beispiel, das die Fähigkeiten der Sprache demonstriert, empfehle ich, ein Rendering-Programm für dreidimensionale Szenen auf der Grundlage der Rückstrahlverfolgung zu betrachten. Es ist sehr organisch verwendete Rekursion, Schnittstellen, dynamische Arrays; etwas künstlicher - Multitasking.

Ein Beispiel für die Einbettung des Umka-Übersetzers in ein C-Projekt ist der Quellcode des ausführbaren Wrappers des Übersetzers. Es gibt auch eine Beispiel-Umka-Spracherweiterung mit externen Funktionen in C.

Bild

All Articles