Last active
July 29, 2021 21:27
Revisions
-
bobbbay revised this gist
Jul 27, 2021 . 1 changed file with 6 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -97,11 +97,11 @@ #+end_src Cool, right? **** Pattern matching Salo supports pattern matching, e.g.: #+begin_src name : Bool -> String name true = "Bob" @@ -127,7 +127,7 @@ With the ~_~ character, Salo can match every other variant. **** Generic parameters Functions don't have to have strict types - with polymorphism, we're able to allow any type to pass into our program, as long as it can validly compile (more on this later). @@ -158,7 +158,7 @@ Anyways, note the ~return~ keyword here. This indicates to Salo that this value should be returned, i.e. this file evaluates to ~true~. *** Imports Salo is also able to import other files using the ~import~ keyword. Imports can either bring a library file or a local file into scope. For example: @@ -182,7 +182,7 @@ #+end_src Assuming =./git.sa= exists and returns an Attrset, the ~git~ value will contain that value. If any Salo rules are violated during the import - the file does not exist or the returned value isn't an Attrset - a compile-time error will be thrown. ** Example configuration #+begin_src salo -
bobbbay revised this gist
Jul 26, 2021 . 1 changed file with 95 additions and 21 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,7 @@ * Salo is a "wrapper language" to Nix * It is statically typed (and type inferred), has an ML-inspired syntax, and provides macros * Each top-level Salo configuration must return an Attrset by the end of the file ** Goals @@ -20,9 +20,9 @@ ** The basics This section outlines the basics of Salo's syntax. If you'd like to skip the basics and check out an actual example, scroll down to the [[Example configuration]]. *** The REPL Before starting, let's get familiar with Salo's REPL. Run ~salo~ in the command line once Salo is installed to open up the prompt: @@ -35,7 +35,7 @@ * ~:t x~: get the type of ~x~ * ~:q~: quit * [TODO] More to come! Now that we're familiar with the REPL, we can continue to learning Salo's configuration language. From this point on, every code block that begins with ~> ~ is run in the REPL. @@ -99,48 +99,122 @@ Cool, right? **** TODO Pattern matching Salo supports pattern matching, e.g.: #+begin_src name : Bool -> String name true = "Bob" name false = "Jeffrey" #+end_src In this case, if the Bool given to ~name~ is true, it will evaluate to "Bob". If it is given false, then it will evaluate to "Jeffrey". Salo pattern matches /must/ be exhaustive. Meaning, this won't work: #+begin_src isOne : Int -> Bool isOne 1 = true #+end_src Salo will complain /during compile time/ that this match does not cover every variant. What if we pass on 5, 6, or 7? Salo has no idea what to evaluate to. This, however, will work: #+begin_src isOne : Int -> Bool isOne 1 = true isOne _ = false #+end_src With the ~_~ character, Salo can match every other variant. **** TODO Generic parameters Functions don't have to have strict types - with polymorphism, we're able to allow any type to pass into our program, as long as it can validly compile (more on this later). Again, similar to Haskell: #+begin_src generic : a -> a -> a generic x y = x + y #+end_src This function will have a different type signature per call. For example, if we run: #+begin_src generic "A" "B" #+end_src The type signature will be ~generic : String -> String -> String~. Salo knows the very second it sees that first argument ~"A"~ that the other two values in the type signature must also be a String. *** Returning Earlier in this document, we mentioned that each top-level Salo configuration file *must* return an Attrset. Now, let's examine /how/ this is done. #+begin_src salo return true #+end_src This is a minimal, valid Salo file. Crazy, right? Just kidding. Anyways, note the ~return~ keyword here. This indicates to Salo that this value should be returned, i.e. this file evaluates to ~true~. *** TODO Imports Salo is also able to import other files using the ~import~ keyword. Imports can either bring a library file or a local file into scope. For example: #+begin_src import std::prelude::*; #+end_src Will import everything in the ~prelude~ module of the standard library. This line is actually automatically inserted into every Salo file for ease-of-use. Note that glob imports are not recommended, but are possible. #+begin_src import ./emacs.sa::backgroundColor #+end_src Will search for =./emacs.sa=. If not found, Salo will throw a compile-time error. If found, it will import the ~backgroundColor~ value in emacs.sa. Finally, we have the ability to import the returned value of a file, e.g. #+begin_src git : Attrset git = import ./git.sa #+end_src Assuming =./git.sa= exists and returns an Attrset, the ~git~ value will contain that value. If any Salo rules are violated during the import - the file does not exist or the returned value isn't an Attrset - a compile-time error will be thrown. ** Example configuration #+begin_src salo description : String; -- type is string description = "A system flake for my x86_64 server"; -- set value -- Note that `description` is not specifically used in the result -- Type is inferred : Array<Derivation> packages = [ pkgs.git -- type is Derivation ]; hardware.pulseaudio = { -- an Attrset enable = true; -- Booleans extraModules = [ pkgs.pulseaudio-modules-bt ]; -- guess what type this is :P package = pkgs.pulseaudioFull; support32Bit = true; extraConfig = " load-module module-bluetooth-policy auto_switch=2 "; -- multiline Strings also work }; -- end of Attrset { networking.hostName = "MyServer", -- can inline value environment.systemPackages = packages, -- can use variable's value as long as the type checks hardware, /* desugars into `hardware = hardware` hardware is an Attrset which contains Attrset, `pulseaudio`. */ } -- Note that the semicolon is omitted here, because this is what will be returned -- If we placed a semicolon here, Salo would complain that nothing is returned #+end_src Evaluates to: -
bobbbay revised this gist
Jul 26, 2021 . 1 changed file with 63 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,25 +1,53 @@ * Salo MVP Welcome to the Salo MVP document. If you're here, you're probably interested in what Salo is, what it hopes to accomplish, and what advantages it provides. Without further ado, let's get started! ** Overview In short... * Salo is a "wrapper language" to Nix * It is statically typed (and type inferred), has an ML-inspired syntax, and provides macros * Each Salo configuration should provide at least one return value by the end of the file ** Goals Salo aims to: * Use a static type system to check code at compile-time * Provide a familiar, ML-like syntax * Give extra functionality to configurations with macros ** The basics This section outlines the basics of Salo's syntax. ** The REPL Before starting, let's get familiar with Salo's REPL. Run ~salo~ in the command line once Salo is installed to open up the prompt: #+begin_src salo-repl > Welcome to the Salo REPL! > #+end_src The REPL supports a few commands: * ~:t x~: get the type of ~x~ * ~:q~: quit * [ ] More to come! Now that we're familiar with the REPL, we can continue to learning Salo's configuration language. From this point on, every code block that begins with ~> ~ is run in the REPL. *** Types Salo has many types, mostly springing off of Nix's types. These include: * Bool * Int * String * Attrset * Array<T> * Derivation * Function @@ -44,15 +72,38 @@ Functions are defined in a slightly different syntax: #+begin_src salo > f : String -> String > f x = x #+end_src Very Haskell-esque, indeed! If you're unfamiliar with ML syntax, this defines a function that takes a String and returns a String. In the implementation, ~f~ takes ~x~ and returns ~x~ without modifications. **** Currying Salo types curry by default. Take the following code example (note the REPL prompt): #+begin_src salo-repl > :t f f : String -> String > g : String -> String -> String > g x y = x + y > :t g g : String -> String -> String > :t g "Hello, " g "Hello, " : String -> String #+end_src Cool, right? **** TODO Pattern matching **** TODO Generic parameters Functions can also have generic parameters, such as ~Array<T>~. Similar to Rust, generic parameters are kept in angle brackets upon declaration: *** TODO Imports *** NixOS @@ -108,4 +159,4 @@ Evaluates to: extraConfig = "load-module module-bluetooth-policy auto_switch=2"; }; } #+end_src -
bobbbay created this gist
Jul 26, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,111 @@ * Salo MVP ** Goals * To use a static type system to check code at compile-time * To provide a familiar, ML-like syntax * To give extra functionality to configuration with macros ** Overview * Salo is a "wrapper language" to Nix * It is statically typed (and type inferred), has a slightly-altered syntax, and provides macros * Each Salo configuration should provide at least one return value, using the `return` keyword or by omitting a semicolon at the final line (similar to Rust's synax) *** Types Salo has many types, mostly springing off of Nix's types. These include: * Bool * Int * String * Attrset * Array\<T> * Derivation * Function Values are created with a (mostly optional) type signature and value, as such: #+begin_src salo a : String a = "Hello, world!" #+end_src This is very similar to ML syntax. In the example above, the definition of ~a~ could have been rewritten as: #+begin_src salo a = "Hello, world!" #+end_src Because Salo is smart enough to infer that ~a~'s type is String. *** Functions Functions are defined in a slightly different syntax: #+begin_src salo f : String -> String f x = x #+end_src Very Haskell-esque, indeed! If you're unfamiliar with ML syntax, this defines a function that takes a String and returns a String. In the implementation, ~f~ takes ~x~ and returns ~x~ without modifications. *** TODO Currying *** TODO Imports *** NixOS To generate a NixOS configuration, an Attrset should be returned. ** Example configuration #+begin_src salo description : String; // type is string description = "A system flake for my x86_64 server"; // set value // Type is inferred : Array<Derivation> packages = [ pkgs.git // type is Derivation ]; hardware.pulseaudio = { // an Attrset enable = true; // Booleans extraModules = [ pkgs.pulseaudio-modules-bt ]; // guess what type this is :P package = pkgs.pulseaudioFull; support32Bit = true; extraConfig = " load-module module-bluetooth-policy auto_switch=2 "; // multiline Strings also work }; // end of Attrset { networking.hostName = "MyServer", // can inline value environment.systemPackages = packages, // can use variable's value as long as the type checks hardware, /* desugars into `hardware = hardware` hardware is an Attrset which contains Attrset, `pulseaudio`. */ } // Note that the semicolon is omitted here, because this is what will be returned // If we placed a semicolon here, Salo would complain that nothing is returned #+end_src Evaluates to: #+begin_src nix { config, pkgs, ... }: { networking.hostName = "MyServer"; environment.systemPackages = [ pkgs.git ]; hardware.pulseaudio = { enable = true; extraModules = [ pkgs.pulseaudio-modules-bt ]; package = pkgs.pulseaudioFull; support32Bit = true; extraConfig = "load-module module-bluetooth-policy auto_switch=2"; }; } #+end_src