Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions daslib/apply.das
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,20 @@ def clone_block_with_name(name : string; blk : ExpressionPtr; hasExtraArg : bool

[call_macro(name="apply")] // apply(value, block)
class ApplyMacro : AstCallMacro {
//! This macro implements the apply() pattern. The idea is that for each entry in the structure, variant, or tuple,
//! the block will be invoked. Both element name, and element value are passed to the block.
//! For example
//! This macro implements the ``apply()`` pattern. For each field in a structure, variant, or tuple,
//! the block is invoked with the field name and value. An optional third block argument receives
//! per-field annotations as ``array<tuple<name:string; data:RttiValue>>``.
//!
//! struct Bar
//! .. code-block:: das
//!
//! struct Bar {
//! x, y : float
//! apply([[Bar x=1.,y=2.]]) <| $ ( name:string; field )
//! }
//! apply(Bar(x=1.0, y=2.0)) $(name, field) {
//! print("{name} = {field} ")
//! }
//!
//! Would print x = 1.0 y = 2.0
//! Would print ``x = 1 y = 2``
def override visit(prog : ProgramPtr; mod : Module?; var expr : smart_ptr<ExprCallMacro>) : ExpressionPtr {
macro_verify(expr.arguments |> length == 2, prog, expr.at, "expecting apply(value, block)")
if (expr.arguments[0]._type != null) {// need value inferred
Expand Down
32 changes: 32 additions & 0 deletions daslib/async_boost.das
Original file line number Diff line number Diff line change
Expand Up @@ -379,3 +379,35 @@ def public async_run_all(var a : array<iterator<auto>>) {
}
}
}


def public async_timeout(var a : iterator<auto>; max_frames : int) : bool {
//! This function runs an async function for at most `max_frames` frames.
//! Returns ``true`` if the async function completed within the limit,
//! ``false`` if it was terminated due to timeout.
var frames = 0
for (t in a) {
frames ++
if (frames >= max_frames) {
return false
}
}
return true
}


def public async_race(var a : iterator<auto>; var b : iterator<auto>) : int {
//! This function runs two async functions concurrently and returns the
//! index (0 or 1) of whichever finishes first. The other is abandoned.
var ta : bool
var tb : bool
while (true) {
if (!next(a, ta) || empty(a)) {
return 0
}
if (!next(b, tb) || empty(b)) {
return 1
}
}
return -1
}
25 changes: 22 additions & 3 deletions daslib/coroutines.das
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ typedef Coroutine = iterator<bool>
//! An array of coroutines.
typedef Coroutines = array<Coroutine>

[macro_function]
def private verify_inside_coroutine(prog : ProgramPtr; call : smart_ptr<ExprCallMacro>&) : bool {
//! Verifies that a call macro is being used inside a [coroutine] or [async] annotated function.
//! Returns true if valid, false if not (and emits macro_error).
if (call.inFunction == null) {
return true
}
for (ann in call.inFunction.annotations) {
if (ann.annotation.name == "coroutine" || ann.annotation.name == "async") {
return true
}
}
macro_error(prog, call.at, "{call.name}() can only be used inside a [coroutine] or [async] function")
return false
}

[call_macro(name="yeild_from")]
class private YieldFrom : AstCallMacro {
//! This macro converts yield_from(THAT) expression into::
Expand Down Expand Up @@ -55,9 +71,10 @@ class private CoContinue : AstCallMacro {
//! That way co_continue() does not distract from the fact that it is a generator<bool>.
def override visit(prog : ProgramPtr; mod : Module?; var call : smart_ptr<ExprCallMacro>) : ExpressionPtr {
//! Visits the co_continue macro call and rewrites it to ``yield true``.
// TODO: verify if we are in coroutine
// TODO: verify if we are in coroutine which returns bool
macro_verify(call.arguments |> length == 0, prog, call.at, "expecting co_continue()")
if (!verify_inside_coroutine(prog, call)) {
return <- default<ExpressionPtr>
}
return <- qmacro_expr() {
yield true
}
Expand All @@ -74,8 +91,10 @@ class private CoAwait : AstCallMacro {
//! The idea is that coroutine or generator can wait for a sub-coroutine to finish.
def override visit(prog : ProgramPtr; mod : Module?; var call : smart_ptr<ExprCallMacro>) : ExpressionPtr {
//! Visits the co_await macro call and rewrites it into a for-yield loop over the sub-coroutine.
// TODO: verify if we are calling co_await on a coroutine.
macro_verify(call.arguments |> length == 1, prog, call.at, "expecting co_await(subroutine)")
if (!verify_inside_coroutine(prog, call)) {
return <- default<ExpressionPtr>
}
let iname = make_unique_private_name("_co_await_iterator", call.at)
return <- qmacro_block() {
for ($i(iname) in $e(call.arguments[0])) {
Expand Down
2 changes: 2 additions & 0 deletions doc/source/reference/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ introduced in earlier tutorials.
tutorials/45_debug_agents.rst
tutorials/46_apply_in_context.rst
tutorials/47_data_walker.rst
tutorials/48_apply.rst
tutorials/49_async.rst

.. _tutorials_integration_c:

Expand Down
6 changes: 3 additions & 3 deletions doc/source/reference/tutorials/44_compile_and_run.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Compiling and Running Programs at Runtime
single: Tutorial; Multiple Contexts
single: Tutorial; Virtual File System

This tutorial covers **compiling and running daScript programs from
daScript** — dynamically compiling source code at runtime, simulating
This tutorial covers **compiling and running daslang programs from
daslang** — dynamically compiling source code at runtime, simulating
it into a runnable context, and invoking exported functions across
context boundaries.

Expand All @@ -32,7 +32,7 @@ section.
Compile from string
===================

The simplest way to compile daScript at runtime is ``compile``, which
The simplest way to compile daslang at runtime is ``compile``, which
takes a module name, source text, and ``CodeOfPolicies``. The callback
receives ``(ok : bool, program : smart_ptr<Program>, issues : string)``.

Expand Down
8 changes: 5 additions & 3 deletions doc/source/reference/tutorials/47_data_walker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ Data Walking with DapiDataWalker
single: Tutorial; Runtime Introspection

This tutorial covers ``DapiDataWalker`` — a visitor-pattern class for
inspecting and transforming daScript values at runtime. You subclass
inspecting and transforming daslang values at runtime. You subclass
it, override callbacks for the types you care about, and walk any data
through RTTI type information.

Prerequisites: basic daScript knowledge (structs, arrays, tables,
Prerequisites: basic daslang knowledge (structs, arrays, tables,
enumerations, bitfields).

.. code-block:: das
Expand Down Expand Up @@ -249,7 +249,7 @@ containing value names. Bitfields trigger ``Bitfield`` with a
JSON serializer — putting it all together
===========================================

A practical walker that serializes any daScript value to JSON.
A practical walker that serializes any daslang value to JSON.
This combines structure, array, table, tuple, and scalar callbacks
into one coherent class. The walker writes to a ``StringBuilderWriter``
for efficiency — no intermediate string concatenation:
Expand Down Expand Up @@ -426,3 +426,5 @@ Quick reference
``VarInfo``, ``EnumInfo``).

Previous tutorial: :ref:`tutorial_apply_in_context`

Next tutorial: :ref:`tutorial_apply`
Loading