# 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.
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 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 
#

# 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 by redirecting the command output and input.
# 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

}