# Muesli is a Multi Use Embeddable Scripting Language Interpreter. # It is a scripting language with a TCL or shell like syntax, but somewhat # OOP and LISP like semantics. # # First it will be an embeddable scripting language implemented in Go. # In what follows I will describe the design of the language though example. # # Why is there a # before these lines? # begins a comment, until the end of the # line. MUESLI does not execute comments but skips them in stead. # Muesli is a line based language. # # Muesli consists of newline separated statements, however, a newline # after { is ignored and does not count as a separator. # # There are also bock comments: #{ This is a block comment, it nests but the {} pairs must match. } # Empty lines are ignored. # Muesly supports a whole range of typed values. # Muesli supports integer constants of type Int p 1 p 2 p 378 p +108 p -878 # It also supports multi line string constants with escapes, of type String p "Hello world\" " # Muesli also supports multi line strings without escapes p ` "Pop" goes the weasel's tail. ` # There are built in identifiers for type Bool or nil p !true !false !nil # Museli has simple floating point constants, but no exponential notation, # of type Float p +0.5 p -7.000005 # Lists can be created between [ ] and may be heterogenous or homogenous. # The [ ] must be space separated. # The type is Any[] if the list is heterogenous. p [ foo "bar" ] # The type is Int[] below p [ 1 2 3 ] # A sequence of a lower case letter followed by anything that is not whitespace. # For example: this-IS*a/single+Word._ # The value of a word is a string with the word itself. # If the word is at the beginning of the line it is invoked as a command. # Muesli's basic syntax is that of the command chain. Spaces separate the # arguments of the command. The first word is the command, # the rest are the arguments. print "hello" world 7 0.9 # the previous command outputs: "hello world 7 0.9" to command output # A command has one or more results that can be captured with a parenthesis. print ( mul 3 ( sum 5 7 ) ) # Commands can be grouped into blocks. The value of the block is that of it's last command. # block { # print "hello" # print "world" # } # Commands can also take blocks as parameters. Don't put a newline between # the open and close of the block to be sure multiple blocks get passed command { print "first block" } and also { print "second block" } # In Muesli all values are typed. Types can be defined by the builtin type # command. User defined types always are derived from Object or from another # built in type. They add the fields mentioned with their given types. type Door Object name String locked Bool keys Int[] # A value of defined type can be created using the new command set door1 (new Door "red door" true []) # Commands can be defined by the built in 'to' command. # They can have many arguments and many results. to openDoor [door Door key Item] Bool { if (contains (member door key) key) { set (member door open) true } } # Methods can be also defined with the to command to Door open [key Item] Bool { if (contains (member door key) key) { set (member door open) true } } # Unlike TCL, MUESLI values are typed, and commands # can be overloaded based on the types the types of their arguments. # Types are much like words, but they begin with an upper case letter, up to the # next whitespace. # A type that end in [] is a list, [][] a list of lists, etc, and a type # that end in ... represents a variable argument, which must be last. # Muesli tries to match the types, from narrow to wide for objects in the order # Outer class, Embedded Class, Object, Any, # and for primitive types , Primitive, Any # You can override commands with more specific ones but not existing ones # that have the same specificity. # To create such an overload you should create a "cover" with the builtin # cover command. Covers are commands that dispatch to other commands based on # the types of the arguments. cover open openDoor[door Door key Item] # Variables are not part of the language but there are builtin commands # to define them. Variables are set in the current scope with set a 10 # And fetched in the current scope with get print (get a 10) # To acces a variable in the scope one above current use upset/upget. upset a 10 # However, there is syntactic sugar: # =foo bar gets mapped to (set foo bar) =a 10 # $foo means (get foo) print $a # combinations of = followed by $ are allowed for indirect variable assignment =indirect a = ($indirect) 20 =$indirect 20 print $a # Or indirect getters print $$indirect # Control structures are merely builtin functions. if (less a 10) { print "Less" } else { print "More" } # A literal command evaluates to itself and writes it's value to command output. 5 # Commands can be chained together using operators. # Operators in muesli are always binary. There are no unary or ternary # operators. # An operator is any token that starts with -+*/|>< and contains no # alphanumeric characters. # The semantics of operators is that the operator is called as if it was # a command, with the first operand as the first argument and the second # operand as the second argument. =foo ( sqrt 2.0 + 3.14 - 2.1 ) # Means the same as # =foo ( sub ( add ( sqrt 2.0) 2.1 ) ) $foo # # There are built in functions for getting, setting the fields and for # sending messages to objects in Smalltalk style. # of object valued types: take $door1 name # "red door" make $door1 name "green door" send $door1 open $key # /*-+&|@#'(^!,?.;=~ # Since these three are common, there is syntax available to # abbreviate this. ?door1 's name # same as (take $door1 name) ?name , door1 (take $door1 name) @door1's name "green door" # same as (make $door1 name "green door") >door1, open $key1 # same as send $door1 open $key1, open must be a # callable method # Muesli default syntax heavily uses "line noise" characters to signify meaning # through a prefix, and has no key words in itself. However, is possible to # define keywords. These get replaced by a single token to reduce the line noise. # This allows to have an English-like or other natural language-like syntax. # For example, with the default English key word list openDoor above can also # be defined as follows: to openDoor list door Door key Item done Bool do if as contains as the door's key so a key so do make a door open true end end # That's all there is to the syntax. Apart from the built in commands, # the semantics are up to you to implement as # embedded commands or operators. # Do note that MUESLI uses dynamic scoping for ease of implementation