OTIL: The One True Implementation Language
What OTIL is
- Part of OfflineOS - it is designed to be tightly integrated with the other programming languages and development tools
- A systems programming language - OTIL is specifically designed for writing the Kernel, dynamic loader and core libraries
- Procedural and Old-School - The primary influences of OTIL are Pascal (syntax) and C (memory-model). Additional ideas have been gleaned from Erlang, Ruby and even Algol.
- Statically and Strongly typed - Any mixing of datatypes without recasting will result in a compilation error. Unless a Slice is involved.
- Readable - Aside from integration with the greater OfflineOS toolchain, the greatest distinction between OTIL and its inspirations is the very high "signal-to-noise-ratio" of the syntax.
What OTIL isn't
- An application programming language - Use MIA instead
- Easy - Readability is a high priority but that doesn't imply that OTIL code should be easy to write.
Concepts
Toolchain Integration
OTIL has been co-designed with MIA for multi-language development and Mac / Build for no-nonsense meta-programming.
Multi-language development
While OTIL and MIA belong to very different paradigms they share a common format for modules so that MIA applications can seamlessly call libraries written in OTIL.
Meta-programming
Like how C/C++ has the C Pre-Processor, OTIL has the Mac macro language. However unlike the C Pre-Processor Mac is not intended for a specific language.
Statements vs Expressions
A statement is one step in the program's advancing state.
An expression are either a value, function call or mathematical equation.
In OTIL expressions only act as clauses of statements.
Syntax
See here
Datatypes
See here
Best Practises
Embed error conditions in data-structures
Global variables are a common source of bugs, especially in conjunction with multi-threading / multi-processing. Instead of a global error status put an error status field into the definition of a record type.
For example:
CONST input : IO.IOString <- IO.ReadLine(file);
IF status OF input = IO.Okay THEN
IO.PrintLine(content of input);
ELSE
IO.PrintLine("Could not read file");
END
Don't short-circuit sub-routines
A common bad habit amongst developers is hiding a return or exit statement in an if clause that does not have a corresponding else clause. This is called short-circuiting and can greatly decrease the readability of a program.
Don't use strings directly
As briefly mentioned in the documentation of the string type, it is highly recommended to wrap this type in a record type that provides additional information about it.
This is primarily because of the unreliable nature of 0-terminated strings.
Under Consideration
- Data ownership tracking / automatic allocation & freeing similar to Rust
- Convention that procedures have a final argument that is a reference to an error status
- Find a way of constructing loops that prevents exit conditions from being buried in conditional clauses
- Not implementing conventional pointers