Deemon is a scripting language with a syntax inspired by C and other languages derived from C, whilst featuring a python-like runtime.
import * from deemon;
print "Deemon is totally rad, right?\n> ",;
local l = File.stdin.readline().strip().lower();
if (l in { "y", "yes" }) {
print "Thank you! :D";
} else if (l in { "n", "no" }) {
print "Aww... You're hurting my feelings :(";
} else {
print "Huh?";
}
Deemon is designed with the following features in mind:
- Being portable to any Unix-like operating system (obviously including Linux), as well as Windows
- Working with, and processing data via sequences and sequence proxies, rather than individually or by always creating new list objects
- Being faster than python while still offering similar runtime functionality (mainly by not having a GIL, a more powerful instruction set, and using static symbol resolution, rather than having locals/globals be runtime hash-mappings)
NOTICE: Deemon uses git submodules (which are required to build deemon), so if you use the download zip function, you won't end up with everything that goes into building deemon. So in order to clone deemon in its entirety, you must clone this git through use of:
git clone --recursive https://github.com/GrieferAtWork/deemon.git
With configure
bash ./configure
make -j $(nproc)
Cross-compiling deemon (using /opt/kos/binutils/i386-kos/bin/i686-kos-gcc
)
bash ./configure --cross-prefix=/opt/kos/binutils/i386-kos/bin/i686-kos-
make -j $(nproc)
With visual studio
- Open
/.vs/deemon-{PlatformToolset}.sln
- Select whichever
PlatformToolset
you have installed - Deemon should be able to compile for any toolset, but sadly there's no way to just tell VS to "use whatever you have installed"
- Select whichever
- Select your preferred build configuration and architecture
CTRL+SHIFT+B
- Modular code design with one script able to import another script's globals
- Sequences anywhere: anywhere expressions appear as
,
-separated lists, it's possible to use a sequence asseq...
, causing its elements to appear as distinct elements. E.g. to concat two sequences, do{ a..., b... }
- Object-oriented programming and classes
- Polymorphism
- Type inheritance, and multiple base classes
- Member functions and properties (getsets)
- Private and public members
- User-defined constructors and destructors
- User-definable operators
- All of your usual C-like statements/expressions
- Co-routines (aka. "yield"-functions)
- Generator expressions (
x = for (local elem: y) if (elem) elem + 1;
) - Java-like lambda functions (
list.sort(key: e -> e.casefold())
) - Type annotations (
local x: {string: int} = Dict();
) - Exceptions and try-catch/finally
- With-statements (
with (lock) { ... }
) - GCC-style statements-in-expressions (
local x = ({ local y = 10; y + 20; });
) - Optionally assigned variables (
local x; if (y) { x = 10; } print x is bound;
) - Default/optional/keyword arguments in functions (
function foo(x, y = 10, z?) {} foo(1, z: "Hello");
) - ...
- Full Unicode support (
assert "²".asnumeric() == 2
)- Fully featured string API (for doing anything you might think of)
- Built-in regular expression support
- Infinite-precision integers
- Sequence, Set, and Map-like built-in containers
- Mutable/Immutable sequences (
List
/Tuple
) - Mutable/Immutable mappings (
Dict
/Dict.Frozen
) - Mutable/Immutable sets (
HashSet
/HashSet.Frozen
) - Everything inherits from a common
Sequence
class providing a fully-featured sequence API
- Mutable/Immutable sequences (
- Everything is reference-counted (automatic cleanup)
- Modules are compiled on first use and automatically re-compiled if modified
- Deemon scripts are compiled and executed as bytecode for better performance
- Full multi-threading support everywhere (everything is thread-safe by default)
- And I mean real multi-threading (i.e. deemon doesn't have a GIL)
- Floating point numbers
- File/std I/O
- Dynamic module imports (
local x = "deemon"; local y = import(x);
) - Execute strings as code (
print exec("(a, b) -> a + b")(10, 20);
)
- Modules are either native shared libraries (
.so
or.dll
), or deemon scripts (.dee
) - Modules for:
- Extra sequence types (
collections
) - Interfacing with C functions and native system libraries (
ctypes
) - Disassembling deemon bytecode (
disassembler
) - System APIs (
fs
,posix
,win32
) - Spawning and controlling sub-processes (
ipc
) - Mathematic functions like
sin
,cos
, etc. (math
) - Low-level networking and sockets (
net
) - Extra threading functionality like locks and TLS variables (
threading
) - Timestamps and time deltas (
time
) - Interfacing with doc strings and other RTTI (
doc
,doctext
, as well as/util/doc-server.dee
) - ...
- Extra sequence types (
Code examples can be found in /util/tut
- Introduction of a module-based dependency system that allows code reuse without relying on preprocessor functionality that really didn't fit a scripting language all too well.
- With more emphasis on documentation, deemon now comes shipped with a documentation server accessible via web-browser
- It should be noted that the documentation server, as well as the RTTI parser are written entirely in deemon.
- Links listed below require this server to be running locally.
- A complete overhaul of the builtin
string
type- Full unicode support all packed together into a single string type
- Separation between raw data
Bytes
andstring
s, as well as functionality to decode/encode data and strings - Builtin support for regular expressions
- Addition of miscellaneous functions such as
indent()
orfindmatch()
to help in situation where the old string type was struggling - Addition of case-insensitive variants of many functions, such as
casefind()
- Introduction of a common base class for any
Sequence
-like type- Includes emulation of any kind of sequence operator, as well as a huge set of member functions, including
find()
,sum()
,operator add
or comparisons - Also introduced are common base classes for set-like, and mapping-like objects
- Includes emulation of any kind of sequence operator, as well as a huge set of member functions, including
- Introduction of ASP (Abstract Sequence Proxy)-like objects to allow for lazy computation in functions like
string.split()
, distributing work load across usage and essentially making such functions O(1) when invoked - Introduction of default, optional, and named function arguments
function foo(a, b = 10, c?)
foo("Hello")
Called asfoo(a: "Hello", b: 10, c: /unbound/)
foo("Hello", "World")
Called asfoo(a: "Hello", b: "World", c: /unbound/)
foo("Hello", c: "Universe")
Called asfoo(a: "Hello", b: 10, c: "Universe")
- Introduction of a same-object / different-object operators
===
and!==
- Introduction of a new syntax for constructing a super-view
foo as Sequence
- Introduction of a new syntax for checking if variables or attributes are bound
if (x is bound) print x;
- Introduction of
with
-statements, useful when dealing with files or locks- To go alongside, 2 new operator
operator enter()
andoperator leave()
were introduced
- To go alongside, 2 new operator
- Introduction of an interactive excution mode
deemon -i
where code is executed, and results are printed in real time - Introduction of a
deepcopy
keyword and operator to go alongside thecopy
keyword- Also includes automatic tracking of recursive objects such as a list containing itself.
- Added support for raw string literals
r"the following are 2 seperate characters: \n"
- Overhaul of exception handlers in user-code now introduces zero-effort exception and finally handlers (as opposed to having a stack of active handlers)
- Overhaul of user-classes which now require member variables to also be declared, significantly improving runtime performance
- Lazy compilation of module source files into pre-compiled file caches improves load time significantly
- Extremely powerful peephole optimization of generated bytecode
- The bytecode generated by deemon has grown so powerful that you can actually write code using it, or have it be printed back to you by a powerful, builtin disassembler (try
deemon -S lib/doc.dee
)- If you look at it, it really has more in common with that of a CISC architecture, featuring admirable text compression rates, while still executing assembly as fast as possible
- Added compiler warnings for various questionable cases (including use of reserved keywords as symbol names)
- I actually took the time to write a copy of the entire interpreter in i386 assembly (by hand), providing a significant performance boost on 32-bit Intel machines.
- The builtin
int
type can have arbitrary precision now, allowing operations with a practically infinite number of digits (though I'm not claiming credit for the implementation; only for the integration and new design centered around it) - Introduction of type annotations
function add(x: int, y: int): int
- Mainly intended for simplified and less redundant documentation, but may also be used for other purposes
- Addition of runtime functionality to execute strings as code
print ([exec from deemon](http://localhost:8080/modules/deemon/i:exec))("10 + 20");
- Uses a seperate JIT compiler that directly executes source text, rather than having to preprocess, parse, assembly and link, before finally executing code.
- Inplace operators now have significantly different operation protocols than regular operators (
x += y;
is emulated asx = x + y;
at runtime when no inplace operator exists)- As a result of this, strings and other immutable types will appear as though they can be used in inplace operations, when in reality they can't.
- As a consequence of this, r-values (such as function return values) cannot be used in inplace operations
- The builtin
int
type is now immutable, meaning that use of integers no longer requires seemingly out of placecopy
statements when passing around integers, or having to create copies when loading them as constants. - Classes now require the user to declare member variables (also: I actually implemented a syntax for super-initialization in constructors)
- Introduction of new symbol classes for extern (aka. imported) and global (aka. exported) objects
- Global variables are created when defining a symbols without a
local
prefix in the global scope, or when explicitly prefixed withglobal
- Global variables (symbols) can be modified by other modules or functions without the need of placing their values inside of a cell (as was, and is still required for local variables referenced in inner functions, or lambda expressions)
- Symbol and module import works the same way it does in python, in addition to allowing you to write either
import symbol from module
orfrom module import symbol
. - Additionally, anywhere a variable can appear, you can also write
foo from bar
which will reference a symbolfoo
from a modulebar
without you having to explicitly import that symbol beforehand.
- Global variables are created when defining a symbols without a
- New style guidelines discourage the use of underscores in symbol names (e.g. it's
seq.nonempty
now, instead ofseq.non_empty()
, which is deprecated) - New style guidelines discourage the use of functions for state checks, or alternate representations (e.g. it's
Thread.hasstarted
now, instead ofThread.started()
, which is deprecated) - Builtin types such as
List
orDict
must now beimport * from deemon;
-ed before they appear as symbols - The builtin type
Set
has been renamed toHashSet
.Set from deemon
is now the base-class for set-like objects- Shouldn't really cause any problems in old code though, because deemon 100+'s
Set
-type has always been broken, and never got fixed - That said, the builtin
Set
object (now calledHashSet
) actually works
- Shouldn't really cause any problems in old code though, because deemon 100+'s
- Not every object can be weakly referenced, and instead of a dedicated keyword
weak
,WeakRef from deemon
is used to construct weak references - Single-element Tuples can now be constructed as
(foo,)
- While deemon 100's compiler configuration handled pretty much any syntax problem as a warning, deemon 200 is default-configured to produce errors, thus preventing faulty code from accidentally being executed
- Inplace source formatting
deemon -F
pack
-expressions to omit parenthesis (foo pack 10, 20
is the same asfoo(10, 20)
)- A fully featured C preprocessor (it's a highly advanced version of tpp, including all of its extensions)
- The
__nth
keyword being used to select secondary variable matches.
#include <...>
You really shouldn't be including files any more. - Use modules instead (they're way better)- Various minor syntax changes to steer usercode to being more uniform (warned about in new code; ignored in legacy code)
- The dedicated syntax for cells (
<foo>
is deprecated and very much discouraged)- Use
Cell from deemon
instead. - Also note that with the introduction of global variables, cell indirection is no longer required in most cases
- Use
- C-emulation of
struct
,extern
,union
, etc.- The runtime-aspect is still available through ctypes, however no longer has a dedicated syntax
- Maintained C-like features that won't go away:
- C-like casts
(int)x
(same asint(x)
) - C-like variable declarations
int x = y;
(same aslocal x = int(y);
) - Struct-initializers in mappings
Dict { .x = "foo" }
(same asDict { "x": "foo" }
)
- C-like casts
alias
-symbol declarations no longer existconst
-symbol declarations no longer exist (optimization automatically detectslocal
/global
variables written only once as constant, and you can usefinal
to enforce write-once behavior)operator ! ()
has been removed, and!foo
invokesoperator bool()
and logically inverts its result (!foo
is the same asfoo ? false : true
)- The
operator move()
constructor has been removed, as well as themove
keyword (emulated with sightly different semantics for legacy code; see below)- Note however that
operator move := ()
(move-assign) hasn't been removed
- Note however that
- Removed the logical XOR operator
^^
(just cast both operands to bool, then use the regular XOR)
Legacy code being detected by it #including any of the old headers
- C-like syntax for attributes
__attribute__((attrib))
,__declspec(attrib)
,[[attrib]]
- Deemon 200 relies less than ever on attributes, and where they are still needed, tags are used
@[attrib]
- Deemon 200 relies less than ever on attributes, and where they are still needed, tags are used
- The millions of
__builtin*
functions have all been removed- Most notable, even
__builtin_object()
is emulated
- Most notable, even
- The
move
keyword is defined as an alias forcopy
- Removed the
weak
keyword - Various keywords that all start with 2 underscores (
__static_if
,__if_true
, etc.) - The old notion of modules no longer exist (The
module
keyword was removed, and theimport
keyword now has a different meaning)