123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- # 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 <Bool|Int|String|Float|Word|Type>, 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
- }
|