Estrita

From Esolang
Jump to navigation Jump to search
Estrita
Paradigm(s) imperative
Designed by User:Aadenboy
Appeared in 2024
Computational class Turing complete
Major implementations None
Influenced by Lua, TypeScript
Influenced None
File extension(s) .est
Estrita's logo.

Estrita (Portugese for Strict) is a parody of TypeScript, being a superset of Lua 5.4 with very strict typing, something Lua is known for not having. Estrita programs are transpiled into Lua programs, but only in a way such that it is unnecessarily obfuscated and unmaintainable, forcing you to continue using Estrita instead of switching over to the new Lua program.


Variable Typing

All newly declared variables require that you provide a valid type after the type declaration operator and before the value assignment operator.

local a = 5 -- Compiler Error: Missing type declaration
local a: number = 5 -- Valid

The variable must then adhere to its declared type for its lifespan. The type may not be redeclared.

a = 7               -- Valid
a = "Hello, World!" -- Compiler Error: Cannot assign type 'string' to type 'number'

The only type that you may not use is nil. Instead, you must declare the type to be optional with a question mark. This is the only way to have the type of a variable be of two options, any other combination is not allowed (i.e. no string or number).

local b           -- Compiler Error: Nil declaration is not allowed
local b: nil      -- Compiler Error: Nil declaration is not allowed
local b: boolean? -- Valid

-- All valid
b = true
b = false
b = nil

any is not a valid type. There is no way to give a variable an any-like type.

Tables and Schemas

Tables are defined separately from other types. Instead of simply using table, you must define a schema (and no, an empty schema is not allowed). Like with type declarations, table schemas cannot be redeclared. If no index is provided, it is assumed to be the first available numerical index. You can use existing values as indexes as well.

local account = {name = "John", balance = 500, id = 1}
-- Compiler Error: Missing table schema
local account: table = {name = "John", balance = 500, id = 1}
-- Compiler Error: Schema provided is invalid
local account: {name = string, balance = number, id = number} = {name = "John", balance = 500, id = 1}
-- Valid
local inverse: {[true] = boolean, [false] = boolean} = {[true] = false, [false] = true}
-- Not practical, but valid
local checklist: {boolean, boolean, boolean, boolean} = {false, false, true, false}
-- Valid

Variable length tables are declared by placing a type in place of the index. You can also use ... for arrays.

local record: {[string] = boolean} = {jan1 = true, mar4 = true}
local array: {number, ...} = {1, 2, 3, 4, 6}

Note that for arrays, every value sequentially is expected to match the type. This accounts for nil.

local array2: {number, ...} = {1, nil, 3} -- Compiler Error: Table provided does not follow schema

local array2: {number?, ...} = {1, nil, 3} -- Valid

... can also be a fixed length.

local array3: {[-5] = number?, ..., [0] = number?, ..., [5] = number?} = {[-1] = 1, [0] = 0, [1] = -1}

local array4: {..., [1] = boolean?} = {[-5] = true, [-3] = true, [1] = true}

Schemas can be reused from a previous table simply by referencing the table. This also works when nesting.

local becky: account = {name = "Becky", balance = -10, id = 2}
local accounts: {account, ...} = {account, becky, {name = "Gerald", balance = 0, id = 3}}

Functions

Functions follow similar structure, where its inputs have type declarations and the output has its own type declaration.

function foo(x: number, y: number): number
    return x^y
end

Unlike variables and schemas, functions are allowed to declare their output as nil.

function log(message: string): nil
    print("Log @"..tostring(os.time())..": "..message)
end

There is also a new never data type for functions that signifies that the program will never halt, or will never continue execution after the function (i.e if os.exit() is called). This data type is however only available to those who have the balls to solve the Halting problem.

function forever(): never
    while true do end
end
-- Compiler Error: type 'never' is not implemented in this compiler

Tuples are declared with commas. A semicolon is required at the end.

function baz(message: string): number, ...;
    local set: {number, ...}
    for i: number = 1, #message do
        table.insert(set, message:sub(i, i))
    end
    return table.unpack(set)
end

Global Scope

Global scope variables are illegal—new variables MUST be declared as local. If you really need to declare a global variable, it must be explicitly declared in _G.

_G uses the schema _G: {[string] = table, _VERSION = number, arg = {string, ...}, (and so on)}. All previous values that aren't a table are granted an exemption in the schema. If you wish to add new values, it must be done so within a table as you cannot modify the schema.