design_muesli.muesli 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. # Muesli is a Multi Use Embeddable Scripting Language Interpreter.
  2. # It is a scripting language with a TCL or shell like syntax, but somewhat
  3. # OOP and LISP like semantics.
  4. #
  5. # First it will be an embeddable scripting language implemented in Go.
  6. # In what follows I will describe the design of the language though example.
  7. #
  8. # Why is there a # before these lines? # begins a comment, until the end of the
  9. # line. MUESLI does not execute comments but skips them in stead.
  10. # Muesli is a line based language.
  11. #
  12. # Muesli consists of newline separated statements, however, a newline
  13. # after { is ignored and does not count as a separator.
  14. #
  15. # There are also bock comments:
  16. #{ This is a block comment, it nests
  17. but the {} pairs must match.
  18. }
  19. # Empty lines are ignored.
  20. # Muesly supports a whole range of typed values.
  21. # Muesli supports integer constants of type Int
  22. p 1
  23. p 2
  24. p 378
  25. p +108
  26. p -878
  27. # It also supports multi line string constants with escapes, of type String
  28. p "Hello world\"
  29. "
  30. # Muesli also supports multi line strings without escapes
  31. p `
  32. "Pop" goes the
  33. weasel's tail.
  34. `
  35. # There are built in identifiers for type Bool or nil
  36. p !true !false !nil
  37. # Museli has simple floating point constants, but no exponential notation,
  38. # of type Float
  39. p +0.5
  40. p -7.000005
  41. # Lists can be created between [ ] and may be heterogenous or homogenous.
  42. # The [ ] must be space separated.
  43. # The type is Any[] if the list is heterogenous.
  44. p [ foo "bar" ]
  45. # The type is Int[] below
  46. p [ 1 2 3 ]
  47. # A sequence of a lower case letter followed by anything that is not whitespace.
  48. # For example: this-IS*a/single+Word._
  49. # The value of a word is a string with the word itself.
  50. # If the word is at the beginning of the line it is invoked as a command.
  51. # Muesli's basic syntax is that of the command chain. Spaces separate the
  52. # arguments of the command. The first word is the command,
  53. # the rest are the arguments.
  54. print "hello" world 7 0.9
  55. # the previous command outputs: "hello world 7 0.9" to command output
  56. # A command has one or more results that can be captured with a parenthesis.
  57. print ( mul 3 ( sum 5 7 ) )
  58. # Commands can be grouped into blocks. The value of the block is that of it's last command.
  59. # block {
  60. # print "hello"
  61. # print "world"
  62. # }
  63. # Commands can also take blocks as parameters. Don't put a newline between
  64. # the open and close of the block to be sure multiple blocks get passed
  65. command {
  66. print "first block"
  67. } and also {
  68. print "second block"
  69. }
  70. # In Muesli all values are typed. Types can be defined by the builtin type command.
  71. type Door ( object locked Bool keys Item[] )
  72. # Commands can be defined by the built in 'to' command.
  73. # They can have many arguments and many results.
  74. to open[door Door key Item] Bool {
  75. if (contains (member door key) key) {
  76. set (member door open) true
  77. }
  78. }
  79. # Unlike TCL, MUESLI values are typed, and commands
  80. # can be overloaded based on the types the types of their arguments.
  81. # Types are much like words, but they begin with an upper case letter, up to the
  82. # next whitespace.
  83. # A type that end in [] is a list, [][] a list of lists, etc, and a type
  84. # that end in ... represents a variable argument, which must be last.
  85. # Muesli tries to match the types, from narrow to wide for objects in the order
  86. # Outer class, Embedded Class, Object, Any,
  87. # and for primitive types <Bool|Int|String|Float|Word|Type>, Primitive, Any
  88. # You can override commands with more specific ones but not existing ones
  89. # that have the same specificity.
  90. # To create such an overload you should create a "cover" with the builtin
  91. # cover command. Covers are commands that dispatch to other commands based on
  92. # the types of the arguments.
  93. cover open open[door Door key Item]
  94. # Variables are not part of the language but there are builtin commands
  95. # to define them. Variables are set in the current scope with
  96. set a 10
  97. # And fetched in the current scope with get
  98. print (get a 10)
  99. # To acces a variable in the scope one above current use upset/upget.
  100. upset a 10
  101. # However, there is syntactic sugar:
  102. # =foo bar gets mapped to (set foo bar)
  103. =a 10
  104. # $foo means (get foo)
  105. print $a
  106. # combinations of = followed by $ are allowed for indirect variable assignment
  107. =indirect a
  108. = ($indirect) 20
  109. =$indirect 20
  110. print $a
  111. # Or indirect getters
  112. print $$indirect
  113. # Control structures are merely builtin functions.
  114. if (less a 10) {
  115. print "Less"
  116. } else {
  117. print "More"
  118. }
  119. # A literal command evaluates to itself and writes it's value to command output.
  120. 5
  121. # Commands can be chained together using operators.
  122. # Operators in muesli are always binary. There are no unary or ternary
  123. # operators.
  124. # An operator is any token that starts with -+*/|>< and contains no
  125. # alphanumeric characters.
  126. # The semantics of operators is that the operator is called as if it was
  127. # a command, with the first operand as the first argument and the second
  128. # operand as the second argument.
  129. =foo ( sqrt 2.0 + 3.14 - 2.1 )
  130. # Means the same as
  131. # =foo ( sub ( add ( sqrt 2.0) 2.1 ) )
  132. $foo
  133. #
  134. # That's all there is to the syntax. Apart from the built in commands,
  135. # the semantics are up to you to implement as
  136. # embedded commands, or by redirecting the command output and input.
  137. # Do note that MUESLI uses dynamic scoping for ease of implementation
  138. #{
  139. BLOCK
  140. PUSHS "More"
  141. CALL print
  142. PUSHBLOCK
  143. PUSHW else
  144. BLOCK
  145. PUSHS "Less"
  146. CALL print
  147. PUSHBLOCK
  148. PUSHI 10
  149. PUSHW a
  150. CALL less
  151. CALL if
  152. }