shelly-shell 0.5.0

A Rust based Unix style shell with a typed and structured language syntax.
check_repl ["id": "CONVERSION_PROTOCOL", "name": "Conversion factories and frozen bindings", "steps": [
    ["type Count = Integer; let \$raw = 7", "quiet", ""],
    ["fn Count::from_integer(\$v: Integer): Count { \$v + 1 }", "quiet", ""],
    ["echo Count(\$raw) \$raw", "output", "8 7"],
    ["fn old(\$v: Integer): Count { Count(\$v) }; let \$factory = `Count::from_integer", "quiet", ""],
    ["fn Count::from_integer(\$v: Integer): Count { \$v + 2 }", "quiet", ""],
    ["echo Count(7) (old 7) (\$factory 7)", "output", "9 8 8"],
    ["fn Count::from_integer(\$v: Integer): String { \"bad\" }", "error", "must declare return type"],
    ["echo Count(7) (old 7)", "output", "9 8"],
    ["fn Count::from_integer(\$v: Integer): any { \"bad\" }", "quiet", ""],
    ["echo Count(7)", "error", "Expected Integer"],
    ["echo (old 7)", "output", "8"],
    ["fn Count::from_integer(\$v: Integer): Count { 1 / 0 }", "quiet", ""],
    ["echo Count(7)", "error", "Arithmetic error"],
    ["echo \$raw (old 7)", "output", "7 8"],
    ["fn Count::from_integer(\$v: Integer): Count { \$v + 2 }", "quiet", ""],
    ["fn local(): Count { fn Count::from_integer(\$v: Integer): Count { \$v + 3 }; Count(7) }; echo (local) Count(7)", "output", "10 9"],
    ["let \$annotated: Count = 7; echo \$annotated", "output", "7"],
    ["echo \$annotated.from_integer 7", "error", "Conversion methods have no receiver"],
    ["type Plain = Integer; fn no_hook(): Plain { Plain(7) }", "quiet", ""],
    ["fn Plain::from_integer(\$v: Integer): Plain { \$v + 10 }", "quiet", ""],
    ["echo Plain(7) (no_hook)", "output", "17 7"],
    ["fn from_string(\$v: String): String { \$v + \"!\" }; echo (from_string \"ok\")", "output", "ok!"],
    ["fn Count::from_string(\$v: String): Count { Integer(\$v) }; echo Count(\"10\")", "output", "10"],
    ["type Count = String; fn Count::from_integer(\$v: Integer): Count { String(\$v) + \"!\" }", "quiet", ""],
    ["echo Count(7) (old 7) \$annotated", "output", "7! 8 7"],
    ["fn Count::from_integer(\$v: Integer): Count { \$v }", "error", "Expected Count"],
    ["echo Count(7)", "output", "7!"],
], "exit": 0]

check_repl ["id": "COLLECTION_CONVERSIONS", "name": "Collection factories and declared types", "steps": [
    ["type Basket = Integer; fn Basket::from_array_integer(\$v: [Integer]): Basket { 1 }; fn Basket::from_array_string(\$v: [String]): Basket { 2 }; fn Basket::from_array_any(\$v: Array): Basket { 3 }; fn Basket::from_hash_string_integer(\$v: [String: Integer]): Basket { 4 }; fn Basket::from_hash_any_any(\$v: HashMap): Basket { 5 }", "quiet", ""],
    ["let \$a: [Integer] = []; let \$h: [String: Integer] = [:]; echo Basket(\$a) Basket(\$h)", "output", "1 4"],
    ["let \$items = [1]; echo Basket(\$items)", "output", "1"],
    ["\$items = [\"x\"]; echo Basket(\$items)", "output", "2"],
    ["let \$mixed: [any] = [1]; echo Basket(\$mixed) Basket([1,true]) Basket([]) Basket([:])", "output", "3 3 3 5"],
    ["fn frozen(\$v: [Integer]): Basket { Basket(\$v) }; fn make(): [Integer] { [] }; fn original(): Basket { Basket(make) }", "quiet", ""],
    ["fn Basket::from_array_integer(\$v: [Integer]): Basket { 6 }", "quiet", ""],
    ["echo Basket(\$a) (frozen []) (original) Basket(make)", "output", "6 1 1 6"],
    ["fn Basket::from_array_integer(\$v: [Integer]): any { \"bad\" }", "quiet", ""],
    ["echo Basket(\$a)", "error", "Expected Integer"],
    ["echo (frozen []) (original)", "output", "1 1"],
    ["fn Basket::from_array_string(\$v: [String]): String { \"bad\" }", "error", "must declare return type"],
    ["echo Basket([\"x\"])", "output", "2"],
    ["fn Basket::from_array_integer(\$v: [Integer]): Basket { 6 }; fn global(): Basket { Basket(\$a) }", "quiet", ""],
    ["echo (global)", "output", "6"],
    ["type Numbers = [Integer]; fn Basket::from_numbers(\$v: Numbers): Basket { 7 }; echo Basket(Numbers([]))", "output", "7"],
], "exit": 0]

check_repl ["id": "IMPLIED_CONVERSIONS", "name": "Default factories, overrides and retained versions", "steps": [
    ["type DefaultCount = Integer; let \$default_factory = `DefaultCount::from_integer", "quiet", ""],
    ["fn default_old(\$v: Integer): DefaultCount { DefaultCount(\$v) }; fn default_direct(\$v: Integer): DefaultCount { DefaultCount::from_integer \$v }", "quiet", ""],
    ["echo DefaultCount(7) (DefaultCount::from_integer 7) (\$default_factory 7) (default_old 7) (default_direct 7)", "output", "7 7 7 7 7"],
    ["fn DefaultCount::from_integer(\$v: Integer): DefaultCount { \$v + 1 }", "quiet", ""],
    ["echo DefaultCount(7) (DefaultCount::from_integer 7) (\$default_factory 7) (default_old 7) (default_direct 7)", "output", "8 8 7 7 7"],
    ["let \$annotated_default: DefaultCount = 7; echo \$annotated_default", "output", "7"],
    ["fn DefaultCount::from_integer(\$v: Integer): String { \"bad\" }", "error", "must declare return type"],
    ["echo DefaultCount(7) (\$default_factory 7)", "output", "8 7"],
    ["type DefaultCount = String; echo (DefaultCount::from_string \"new\") (\$default_factory 7) (default_old 7)", "output", "new 7 7"],
    ["type DefaultItems = [Integer]; let \$default_items = `DefaultItems::from_array_integer", "quiet", ""],
    ["fn DefaultItems::from_array_integer(\$v: [Integer]): DefaultItems { [\$v...,9] }", "quiet", ""],
    ["echo DefaultItems([1]).count (\$default_items [1]).count", "output", "2 1"],
    ["type BadDefault = Missing", "error", "Unknown type"],
    ["type BadDefault = Integer; echo (BadDefault::from_integer 7)", "output", "7"],
], "exit": 0]