# 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 they are collected # for documentation purposes. More on that topic later # Muesli is a line based language. # # Muesli consists of newline separated statements, however, a newline # after { or the do keyword is ignored and does not count as a separator. #{ This is a block comment, it nests but the {} pairs must match. } # Empty lines are ignored. # ... # Muesli supports integer constants with type Int p 1 p 2 p 378 p +108 p -878 # It also supports multi line string constants with escapes, with type String p "Hello world\" " # and multi line strings without escapes p ` "Pop" goes the weasel's tail. ` # Built in identfiers for type Bool or nil p !true !false !nil # And simple floating point constants, but no exponential notation, with 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 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. 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 standard 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. type Door ( object locked Bool keys Item[] ) # Commands can be defined by the built in 'to' command. # They can have many arguments and many results. to open[door Door 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 open[door Door key Item] # Variables are not part of the language but there arebuiltin 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" } # 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. # Do note that MUESLI uses dynamic scoping for ease of implementation #{ BLOCK PUSHS "More" CALL print PUSHBLOCK PUSHW else BLOCK PUSHS "Less" CALL print PUSHBLOCK PUSHI 10 PUSHW a CALL less CALL if }