5.7. libDaScriptNano
The daslang runtime with no compiler in it - for programs that run already-compiled daslang and never compile any.
You compile your script to C++ ahead of time on your workstation:
daslang utils/aot/main.das -- -ctx my_script.das generated/
and link the result against nano instead of libDaScript. The generated
my_script.das.h gives you a plain C++ class:
#include "daScript/nano_print.h"
#include "my_script.das.h"
int main () {
das::das_nano_set_print(&my_log_sink); // where print goes
my_script::Standalone ctx; // construct it
int answer = ctx.my_exported_function(21); // call it
}
No daScript.h, no module registration, no Program, no file system. The
context is an object with a lifetime.
5.7.1. What it costs
The examples under examples/standalone/, next to the equivalent program on the
full runtime. .exe is x64 MSVC; .text is arm-none-eabi-gcc 13.2 for a
cortex-m4 with -Os --gc-sections and newlib.
program |
tier |
x64 |
cortex-m4 |
|---|---|---|---|
|
POD compute, no heap |
136 KB |
75,540 |
|
arrays, tables, |
148 KB |
80,612 |
|
lambdas, function pointers, generators |
154 KB |
84,420 |
|
C drives the loop, das decides, |
166 KB |
91,520 |
|
a CSV baked into a table by the compiler |
144 KB |
78,028 |
full-runtime standalone context, for scale |
472 KB |
- |
The x64 column includes the platform’s C runtime, so what it measures is the
difference nano makes on a host, not an embedded footprint. The cortex-m4 column
is the real one: of 01_pure’s 75,540 bytes, roughly 29 KB is the nano runtime,
10 KB the compiled script, and the rest the C library. ARCHITECTURE.md says
where the C library goes and what is worth trimming.
Most of what is left is decided by the program, not by nano. A script that says
var x : double links double soft-float; one that says is Foo needs RTTI. The
runtime is the floor, and the floor is not where the interesting savings are -
which is what 05_compile_time_table is about.
5.7.2. Doing the work at compile time
05_compile_time_table reads a thermistor calibration CSV while the script
compiles, inverts the curve and bakes an evenly spaced lookup table into the
generated C++. The file, the parser, the search and the interpolation stay on the
workstation; the device gets a table, an index and a lerp. Nothing in the linked
image can parse anything - strtol, strtod, sscanf, atoi, fopen and
fread are all absent from it.
That is the argument for this tier. The runtime being small is worth something, but a macro that moves a whole computation to build time is worth more, and daslang macros are ordinary daslang.
5.7.3. What it leaves out
A script that reaches past what nano carries fails to link - the boundary
announces itself at build time rather than becoming a program that quietly grew.
Absent: string interpolation and the string builders (this is where fmt comes
back), every builtin module including math, the GC, the debugger, the JIT, the
serializer, the profiler, threads, and the file system.
Panic and fatal messages format through nano’s own integer-only formatter: %s,
%d/%i, %u, %x, %p and %%, with l/ll widths - no floats, no field
width or precision. Scripts printing floats still work (that path uses the C
library’s snprintf, and only links it when a float is actually printed); it is
the embedder-facing das_fatal_log/panic formatting that is deliberately this
narrow.
ARCHITECTURE.md beside this file explains what nano is made of and lists the
trades it makes.
5.7.4. Building it
In this repository nano builds as part of the normal CMake configure, and the
examples build with it. Outside it, point DASLANG_NANO_ROOT at an installed
SDK root and add_subdirectory this folder:
set(DASLANG_NANO_ROOT "/path/to/daslang-sdk")
add_subdirectory("${DASLANG_NANO_ROOT}/nano" nano_build)
# Anything linking nano lets nano decide the header search order.
set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES "")
add_executable(my_program main.cpp generated/my_script.das.cpp)
target_include_directories(my_program PRIVATE generated)
target_link_libraries(my_program PRIVATE libDaScriptNano)
That set_property line is load-bearing, not tidiness: without it your target
compiles against the full runtime’s headers while linking nano’s library.
ARCHITECTURE.md says why under “The include-order trap”.