It automatically prevents all memory leaks. It doesn't use GC, so no pauses. It's compiled to machine code. It's crazy safe and fast.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
Argentum threads act as lightweight processes that share the same address space.
Immutable objects are freely shared across all threads while mutable ones belong to exactly one thread. Though threads can pass mutable objects one another.
Threads can acts as workers having no internal mutable state or as microservices with state.
Threads communicate with task queues. So no synchronization primitives needed, no races, no deadlocks.
Moving to multithreaded mode didn't turn reference counters into atomic ones.
Example:
using sys{ Object, Thread, setMainObject, log }
class App { // Holds mutable state of the main thread.
// Worker thread, having Object as its internal state.
worker = Thread(Object).start(Object);
}
app = App;
setMainObject(app);
log("Started on main thread\n");
// Post a new "workerCode" task to the worker Object
// Since it's passed to the object of other thread
// this code will be executed on that thread.
app.worker.root().&workerCode(callback &()) {
log("Hello from the worker thread\n");
// Post another task, that we received as a parameter
callback~();
}~(app.&endEverything() {
// This "endEverything" task is connected to the
// main thread object. So it will be activated
// on the main thread. We pass in to the `callback`
// parameter.
log("Shutdown from the main thread\n");
// `?Object` is a null-pointer of type `Object`.
// `setMainObject` here deletes previous App instance
// and as such stops worker thread.
// And since there is no application state object anymore,
// application ends.
setMainObject(?Object);
});
This code uses one existing and one new operator
Create delegate:
receiver.&delegateName(parameters) { code }
Post delegate to its `receiver` thread queue as an asynchronous task and transfer all parameters to that thread
delegate~(parameters);
More details: https://aglang.org/multithreading/
New Windows demo: https://github.com/karol11/argentum/releases
with `src\threadTest.ag` example.
Argentum compiler builds a DWARF-compatible debug info, And it's all integrated with VSCode:
So far it supports:
It has special handling for pointers to functions, lambdas and delegates, strings and limited support for arrays (it shows only 20 first elements).
So far it shows only static type of object by pointers. As a temporary work-around you can use watch expressions with type casts (they can also be used to access any array elements beyond 20 elements boundary).
All details are here: https://aglang.org/argentum-debugger-v1/
There is a famous song:
/*
99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.
...
1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
*/
This song is sometimes used in computer science to compare languages wikipedia.
And even more, there is a dedicated website, that collected 1500+ variations of this program in different languages.
Let's look how this program can be written in Argentum:
using sys {String, log}
using utils { forRange }
using string;
forRange(-99, 1, (count) {
bottles = (c, n) {
c == 0 ? "{}
{n}o more bottles
" : "{}
{c} bottle{c != 1 ? "s"}
"
};
log("{}/
{bottles(-count, "N")} of beer on the wall, {bottles(-count, "n")} of beer.
{count == 0
? "Go to the store and buy some more"
: "Take one down and pass it around"
}, {bottles((99 - count) % 100, "n")} of beer on the wall.
");
})
Unlike code in Wikipedia, this solution does the thing:
All in all, despite its young age Argentum succeeded in solving this question in a straightforward and effective way (it compiled to 20k standalone Windows executable).
Argentum classes and interfaces can be parameterized:
class UnorderedMap(Key, Value) { ... }
interface InStream(T) { ... }
These parameters can be used in inheritance, field and method declarations as well as inside methods.
class Map(K, V) {
+Array(Pair(K, V)); // Base class parameterized with our class parameters
getAt(key K) ?V { ... } // Class parameters affect types of method prototypes
setAt(key K, newVal V) { ... }
forEach(visitor (K, V)void) { ... } // visitor lambda is typed with class parameters.
...
}
class Pair(A, B) {
a = ?A; // field `a` of type `Optional(A)` initialized with `none`
b = ?B; // Field types also depend on class parameters.
}
Right now the internal implementation of generics is does not allow instantiation-of and casts-to the parameters, but I can easily add them to the language in the future.
So bottom line is:
These generics do not introduce additional code, do not consume memory and do not cost CPU time.
result = db.query("{} SELECT name, id FROM users WHERE name LIKE '{ encodeSql(request.userMask) }%' LIMIT {request.page * xPageSize}, {xPageSize}; "); request.mode == Json ? response.send(result.toJson()) : response.send("{} <ul>{ result.forRecords((record) { "{} <li data-id="{ record["id"] }"> { record["name"] } </li> "}) }</ul> ")
In this example we use string interpolation twice:
This SQL query is a simple multiline text string with { placeholders } . Placeholders are Argentum expressions that return everything convertible to strings.
HTML example demonstrates two nested interpolated strings - one for <ul> and one for nested <li>s.
More on string interpolation: here.
// Program
log("
Hello,
I'm a multiline "raw" string
");
// Prints:
Hello,
I'm a multiline "raw" string
These strings have no problems of their siblings in other languages:
More examples and details are here: multiline-string-constants
Argentum can natively call C/C++ functions, pass primitives, objects and raw structures (with sys_Blob object). Example:
In C/C++
#include <stdio.h>
#include "../argentum/src/runtime/runtime.h"
bool ag_fn_io_writeFile(AgString* name, AgString* content) {
FILE* f = fopen(name->ptr, "wb");
if (!f) return false;
bool r = fputs(content->ptr, f) >= 0;
fclose(f);
return r;
}
In Argentum (file io.ag):
using sys { String; log; }
fn writeFile(name String, content String) bool;
writeFile("1.txt", "File data") ? log("done")
More details are here: ffi-tutorial
Anrgentum objects can be turned immutable with prefix freeze operator "*".
class Point {
x = 0;
y = 0;
set(x int, y int) this { this.x := x; this.y := y; }
}
p = *Point.set(10, 42);
// now point p is immutable
p.x += 1; // compilation error, `p` is *Point, and cannot be modified.
Immutable objects are shared across object hierarchies and threads.
There can be declared a methods, specifically callable to immutable objects and methods that cam be called on any objects - regardless their mutable status:
class Node {
name = "";
chilren = Array;
-isLeaf() bool { children.size() == 0 }
}
// method `isLeaf` can be called on any Node - frozen or not
Frozen pointers can reference one object from different other objects. They represent the "aggregation" relationships in terms of UML. With adding of this mechanism Argentum now supports all UML object relations:
Details are here: http://aglang.org/.....shared-pointers-to-immutable-objects
Each object can tell who is its parent.
These parent pointer are maintained automatically at a very low cost (single move instruction).
This ability simplifies the handling of document data models and can facilitate integrity checks if needed.
sys_getParent(existingObject)
Function sys_GetParent returns
Function result is ?sys_Object.
This parent pointers also assist a new "splice" operation, that allows to extract an existing object from one part of the object hierarchy and insert it in other place:
temp = object.field; // save the link to object stored somewhere
object.field := newValue; // make it not stored there anymore
// or
object := newValue; // or destroy the hierarchy it belonged
anotherParentObject.field @= temp // "splice" this object in another place.
This allows to reorganize object hierarchies in safe and effortless manner (previously it required a copy operation).
Today Argentum got small but fundamental improvements:
How it was previously (file `demo.ag`):
using sdl;
using utils;
using gui;
class Scene{
+gui_Group;
sdl = sdl_Sdl;
w = sdl_Window;
rnd = utils_Random;
flare = sdl_Texture;
star = sdl_Texture;
background = sdl_Texture;
foreground = sdl_Texture;
...
How it is now:
using sdl { Window, Sdl, Texture }
using gui { Actor, Group }
class Scene{
+Group;
sdl = Sdl;
w = Window;
rnd = Random;
flare = Texture;
star = Texture;
background = Texture;
foreground = Texture;
Previously any compound names like `sdl_image_mySurface` were able to be created and used in any package. And they always had to be written in full.
Since now names should follow rule: `packageName_functionOrClassName` (for example: `sdlImage_mySurface` or from example above `demo_Scene`. And since names are bound to a module, no need to write them in that long form.
All names defined in a module `demo` are automatically `demo_*`.
When a module declares some dependency with the `using` directive, it may list all names to import and use in short form: `using gui { Actor; Group; }`
If names from different imports collide, give them aliases: `using gui { Control=Actor; }`
Now `Control` can be used instead of `gui_Actor`.
TL;DR: Argentum names just got better.
More on names: link
New compiler and stdlib version: windows demo
Create an account to leave a comment. Already have an account? Log In.
Hellow, Andrey!
I have a few questions:
1) it looks like it's Windows only now - how difficult it is to support other OS (Linux or iOS)?
2) it's 64-bit x86 only, isn't it? how difficult it is to add new architecture (ARM or RISC-V)?
3) according to this
https://aglang.org/how-the-argentum-language-makes-fast-dynamic_cast-and-method-dispatch-with-just-four-processor-instructions/
you have both classes and interfaces - any plans for "mixins"? ;)
Hi there,
1.
Yes, I have plans for every planform. In fact the first iterations were originally developed on Linux. As soon as I complete a couple of last milestone-1 features, I'll port it back to Linux and add WASM and Android and maybe iOS/OSX.
2.
I believe that 32-bit architectures will die sooner than the product will hit the first release. So I have no plans for supporting the 32-bit floats and ints. But everything might change later.
Regarding ARM/RISC-V, I'll definitely add its direct support, but it might work right now with llvm tool chain. Try:
`agc -g -emit-llvm -S -src \argentum-demo\src -start graph -o graph.ll`
this makes you a llvm bitcode text, that can be compiled to any arch with
`clang -o0 -c graph.ll -o graph.o`
and linked accordingly with `src/runtime/runtime.*`
3.
Yes. I have plans for mixins, in fact they will have a pretty trivial implementation. But it's for milestone 2.
Become a member to follow this project and never miss any updates
Have you heard about Aligned Strings format ?