Functions (and classes) are “values” – they can be assigned to variables, passed to functions, etc.

Function arguments can have default values

Function calls can use named arguments, in which case order is not significant. If a value isn’t supplied for named argument, it defaults to true.

Semicolons are not required (but are allowed)

Variables do not need to be declared, and may contain any type – i.e. Suneido is a dynamically typed language

is, isnt, not, and, or are normally used but ==, !=, !, &&, || are allowed

Suneido includes all of the C/C++ operators, including assignment operators (e.g. *=), increment, decrement, and bit manipulation, and adds regular expression operators =~ and !~

Automatic conversions between numbers and strings.

String concatenation is done with the “$” operator, not by overloading “+”. This makes “123” + 456 and 123 $ “456” unambiguous.

Suneido includes the same control statements as C/C++ if-else, while, do-while, switch, but unlike C/C++ conditions must evaluate to true or false or you’ll get an error. Switches are also slightly different – you can’t “fall through” cases, and cases allow multiple

expressions rather than integer constants. There is also a “foreach” statement (see below).

Suneido has a single numeric type – decimal floating point. Keeping numbers in decimal rather than binary allows exact representation of decimals, e.g. for amounts of money. Numbers have 16 digits of precision with an exponent range of plus or minus 127.

Strings are not null terminated so they can store arbitrary binary data as well as text. Strings are immutable i.e. there is no way to “modify” an existing string. (Objects are the only basic data type that is mutable.) This means that substring (s.Substr(i,n)) does not need to do any copying – it just creates a new string that points to part of the old one. For speed, concatenation is “lazy”; it creates a linked list of string segments, which are automatically combined when a single string is required. This greatly reduces the amount of allocation and copying required to manipulate strings.

Suneido could be called a “pure” object-oriented language in the sense that all values (including literals) are “objects” that can have methods. For example:

"hello world".Substr(3,2) => "lo"
97.Chr() => "a"

However, unlike some object-oriented languages such as Smalltalk or Java, Suneido has standalone functions as well as methods in classes.

User defined methods can be added to the built-in classes by creating methods in specially named classes: Numbers, Strings, Dates, Objects, etc.

Suneido has only two “scopes”, global and local. Global names must be capitalized i.e. start with an upper case letter. Globals are either builtin (to the executable) or user defined in libraries in the database. Global names are not variables – they cannot be assigned to by code. Names that start with a lower case letter are local to a single function. Currently there are no packages or modules with separate namespaces.

Like Java, Suneido compiles to a stack oriented “byte code” which is then interpreted. For example:

Linking is done dynamically at run time. This means there are no restrictions on compiling code with calls to undefined functions or inheriting from undefined base classes. Of course, if you try to actually access something undefined, you’ll get a run time error.

Objects

Suneido has a single “universal” container type – objects. Unlike languages like Python or Ruby, you don’t have to worry about what type of container to use. Objects can be used as vectors (single dimensional arrays) or as “maps” or both at the same time. Internally, objects have a vector part and a hash map part. Classes and instances are implemented as objects containing methods and data members.

try Database(“destroy mytable”)
An uncaught exception calls a Handler function – defined in the standard library as the debugger.

You can throw your own exceptions:

if (x < 0)
throw "square root: invalid negative argument: " $ x

Blocks

Suneido supports Smalltalk style “blocks”. Basically, a block is a section of code within a function, that can be called like a function, but that operates within the context of the function call that created it (i.e. shares its local variables).

Blocks can be used to implement user defined “control constructs”. (In Smalltalk, all control constructs are implemented with blocks.) For example, you could implement your own version of “foreach”:

Suneido treats a block immediately following a function call as an additional argument.

Blocks can also be used to execute sections of code in specific “contexts”. For example, the Catch function traps exceptions and returns them. (This is useful in unit tests to verify that expected exceptions occur.)

Within a method, the special name “this” refers to the current object. So members and methods of the current object can be referred to as “this.name” but this is normally shortened to simply “.name”.

Member / method names are public if they start with an upper case letter and private if they start with a lower case letter. Private names can only be accessed by methods of the class. In the above example, “Next” is a public method and “count” is a private member.

New is the constructor. (C++ and Java use the name of the class instead of “New”, but this wouldn’t work for Suneido because it allows “anonymous” classes i.e. with no name.) Base class New’s are automatically called first. You can supply arguments to base class constructors by making the first statement of New a call to “super”. (Similar to Java.)

Normally, “calling” a class is the same as creating an instance. (This can be changed by defining a method called “CallClass”.) So the following are equivalent:

ctr = counter(5)
ctr = new counter(5)

Any method in Suneido can be a “class” or “static” method, providing it doesn’t need to set any members. If a method is called on a class rather than an instance, “this” will be the class itself, and therefore read- only.

If a nonexistent member is accessed, Suneido will call a method with the same name with no arguments, if present. This allows you to change a data member to a method without having to alter code that uses it. (Bertrand Meyer calls this “Uniform Access” – a client should be able to access a property of an object using a single notation, whether the property is implemented by memory or computation.)

If a nonexistent method is called, Suneido will call a method called “Default” if it is present. This can be used to implement delegation, or to handle methods that are not pre-determined.

Since classes and instances are objects, and have methods to get their base class, it is easy for code to inspect methods and members. Java calls this “reflection”.

Stack.Members()
=> #("Pop", "Top", "Push")

Object syntax can also be used to access methods or members “indirectly”: