Sage
Tusk Language
Welcome to Sage
Volume (4%) Hide Volume
Topics
Presenting Tusk

Introduction

First Trust has been using MiniCalc for 25 years to solve a wide variety of problems. Despite its ubiquity and effectiveness, MiniCalc has many drawbacks, and is loved only by its creator and one other developer.

With 25 years of hindsight, we now have a very good idea of what we want in a scripting language: much more Delphi compatibility along with tight integration with the host application, including support for our data types and libraries.

We have built a next generation version of MiniCalc, to address the shortcomings of the original. Even MiniCalc's name is outdated: it reflects the language's initial purpose (tiny calculations), but not its current role at First Trust. Thus, the new version comes with a new name:
Tusk
.

Top 5 Improvements over MiniCalc

Tusk improves upon MiniCalc in many ways, offering enhanced type safety and similarity with Delphi. Here are five of the most significant enhancements…

  1. Type Safety (Parse-Time Error Detection)

    Tusk catches errors like misspelled identifiers and incorrect function arguments during parsing, before any code runs. MiniCalc only detects these issues at runtime, and only if the problematic code is actually executed.

    In MiniCalc, everything is a Variant, with runtime type checking only. In contrast, Tusk implements a robust parse-time type system with declared return types, typed parameters, typed variables/constants, and safe implicit type casts. This provides the benefits of static typing (catching type errors early, better code documentation) while maintaining runtime flexibility.

    MiniCalc was "run and hope"; Tusk is "parse and know".

  2. Static (Lexical) Scoping

    Tusk uses static scoping like Delphi, while MiniCalc uses dynamic scoping. This makes Tusk code behavior more predictable and easier to reason about, since variable resolution depends on where code is written, not where it's called from.

  3. Direct Support for More Delphi Data Types

    Tusk directly supports dynamic arrays (with proper reference semantics), records with their full methods/properties, proper enums (stored as integers), sets, and generics in ways that match Delphi's behavior. MiniCalc uses workarounds like variant arrays and string representations that have different semantics, lower performance, and compatibility issues.

  4. Better Compatibility with Delphi Syntax

    MiniCalc lives in the same neighborhood as Delphi, but Tusk and Delphi are roommates. Tusk delivers improved Delphi compatibility in many ways, but here are some highlights…
    • No @-Sign for Globals
      Tusk avoids MiniCalc's convention of prefixing global identifiers with an @-sign. Instead, Tusk supports the same dot notation that Delphi uses to specify a unit. Additionally, Tusk offers the Topmost Operator, which refers to the top-most definition of an identifier.
    • Calling Zero-Argument Routines
      Unlike MiniCalc, Tusk does not require an empty set of parentheses when calling a procedure or function with zero arguments. Instead, the empty parentheses are optional, like in Delphi.
    • Mixing Boolean and Relational Operators
      MiniCalc does not conform to Delphi's operator precedence in several ways. Tusk mirrors Delphi's operator precedence, but with a key enhancement: Tusk does not allow "under-parenthesized" expressions. Specifically, MiniCalc and Delphi differ as to how to interpret the expression a < b and c > d, while Tusk simply rejects it until you add parentheses to clarify your intent – for example, (a < b) and (c > d).
    • The Result Variable
      Unlike MiniCalc, Tusk supports the familiar Result variable in function definitions. Naturally, Tusk also supports the Exit keyword.

    One language, one mindset, two tools: Delphi for compiling, Tusk for scripting.

  5. Exposing and Documenting Global Routines

    MiniCalc's approach to exposing global routines is ad-hoc and disorganized. Some routines have different names in MiniCalc, such as @ToDateTime, which simply calls DSVarToDateTime. Others look like familiar Delphi routines, but behave in surprising ways. For example, @Length does indeed return the length of a string, but it also works on interfaces (maps, lists, and sets), which is handy, but not compatible with Delphi. Another example is @Inc, which looks like it might increment a value, but in reality, it's a case-sensitive "in" operation.

    Tusk avoids these pitfalls by directly exposing routines from the Delphi RTL and our own libraries – same routine names, same arguments, same behavior. Along related lines, Tusk includes machine-generated runtime library documentation, which is more complete and reliable than MiniCalc's hand-maintained library documentation.

MiniCalc runs your code; Tusk understands your code.

Top 5 Improvements over Delphi

Tusk offers a much higher degree of Delphi compatibility than MiniCalc does. Tusk makes several improvements over Delphi, most of which can be disabled when maximum Delphi compatibility is the priority. Here are five of the most significant features…

  1. DSFormat Validation

    In Tusk, calls to DSFormat are validated at parse time, identifying problems such as too few arguments and arguments of the wrong type. This validation applies to other global routines and methods of records and interfaces that implicitly call DSFormat (for example, certain overloads of DSRaise).

  2. The Any Type

    Tusk introduces a new type, Any, which is like Variant, but without all the annoying limitations. Any is compatible with all data types, including sets, functions (anonymous methods), pointers, and records. When storing a dynamic array into an Any, a reference to the array is used (instead of copying the data into a variant array, as happens with a standard Variant). You can go from an Any to an interface or anonymous method without a cast (as would be required with a standard Variant).

  3. JSON Superset

    Like JavaScript and TypeScript, Tusk is a superset of JSON. In other words, every valid JSON document is also a valid Tusk program, with the same meaning. Two Tusk features that enable this compatibility are object literals and JavaScript string literals.

  4. Strict case Statements

    Tusk offers an enhancement to the case statement, making it a parse-time error to omit one or more choices. This feature is particularly useful for enumerated types.

  5. Function Result Enhancements

    Tusk includes two enhancements related to function results — Result is never aliased to another variable and Result is always zero-initialized. On a related note, all variables are zero-initialized (they never start with a "garbage" value).

Tusk has Delphi's clarity and safety with less of the ceremony that would weigh down a scripting language.

More Information

For more detailed information on Tusk, consult the following resources…

Tusk is powerful like Delphi, flexible like a script, safe like a compiler.

Last Modified: 2/2 4:18:25 pm
In this article (top)  View article's Sage markup
2/2 4:18:25 pm