# 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

}