guild icon
Toit
#Is there a way to build / flash, while ignoring code sections
Thread channel in help
addshore
addshore 03/18/2025 10:11 AM
I c++ I can do something like

#ifdef FOO_BAR doStuff(); #endif

Is there a similar way to do this sort of thing with toit?

The primary usecase for me would be to entirely avoid building verbose log lines, which in their call might create long strings etc, when there is no expectaiton for that log line to every be used?
The only alternative right now I guess would be commenting and un commenting lines continually?
addshoreOPaddshore
I c++ I can do something like #ifdef FOO_BAR doStuff(); #endif Is there a similar way to do this sort of thing with toit? The primary usecase for me would be to enti...
floitsch
floitsch 03/18/2025 10:19 AM
If you use if SOME-GLOBAL-CONSTANT: then the compiler will remove the dead code if it can see that the constant is false.
floitsch
floitsch 03/18/2025 10:21 AM
Another approach is sometimes to make the string construction be block based. For example:
my-log [block]: if SHOULD-LOG: print block.call SHOULD-LOG ::= true main: my-log: "$(expensive) construction of some long string"
floitsch
floitsch 03/18/2025 10:22 AM
This would still do a call and an if, but the expensive contruction would not be done (if SHOULD-LOG is set to false).
addshore
addshore 03/18/2025 01:47 PM
thats quite neat,and could allow me to define my own log levels?

LEVEL-DEBUG ::= 4 LEVEL-TRACE ::= 5 LOG-LEVEL ::= LEVEL-DEBUG do-log-debug [block]: if LOG-LEVEL >= LEVEL-DEBUG: print block.call do-log-trace [block]: if LOG-LEVEL >= LEVEL-TRACE: print block.call main: do-log-debug: "$(expensive) construction of some long debug string" do-log-trace: "$(expensive) construction of some long trace string"

Or would this not get optimized down during compilation?
floitsch
floitsch 03/18/2025 01:47 PM
Simple expressions are also optimized away.
💟1
floitsch
floitsch 03/18/2025 01:47 PM
But I will check now :🙂:
🤣1
floitsch
floitsch 03/18/2025 01:51 PM
ᐅ toit tools snapshot bytecodes /tmp/out.snapshot do-log- Bytecodes for methods[2]: (only printing elements matching: "do-log-") 259: do-log-debug /home/flo/tmp/cp.toit:5:1 0/ 263 [016] - load local 2 1/ 264 [055] - invoke block S1 3/ 266 [053] - invoke static print <sdk>/core/print.toit:13:1 6/ 269 [090] - return null S1 1 272: do-log-trace /home/flo/tmp/cp.toit:8:1 0/ 276 [090] - return null S0 1(edited)
addshore
addshore 03/19/2025 08:19 AM
So thats a yes? :😉:
floitsch
floitsch 03/19/2025 08:19 AM
Yes :🙂:
💟1
addshore
addshore 03/19/2025 11:10 AM
So, the answer is probably that I should go and try and run this bytecode snapshot tool myself :😄:
But i wonder if sometihng like this would still work in terms of keeping things light at complication time?
(Still a simple expression, but its only evaulated in a class instance)

import lite-logging log ::= lite-logging.new-default lite-logging.DEBUG-LEVEL main: log.debug: "Hello, world!"

and

import log import .levels new-default level/int -> Logger: return Logger log.default level class Logger: logger /log.Logger level /int constructor .logger/log.Logger .level/int: logger = logger level = level debug [block]: if level >= DEBUG-LEVEL: print block.call
floitsch
floitsch 03/19/2025 11:19 AM
You mean at runtime?
floitsch
floitsch 03/19/2025 11:20 AM
Here you don't have static constants anymore so there will be a check
addshore
addshore 03/19/2025 11:27 AM
I did try something like

import lite-logging LITE-LOG-LEVEL ::= lite-logging.DEBUG-LEVEL log ::= lite-logging.new-default main: log.debug: "Hello, world!"

first, but LITE-LOG-LEVEL is not accessible in the class
addshore
addshore 03/19/2025 11:27 AM
But basically I was aiming for something there toy could define the log level at the top of your own code, but take advantage of a little package to implement the block style logging methods
floitsch
floitsch 03/19/2025 11:28 AM
That's not really possible.
floitsch
floitsch 03/19/2025 11:29 AM
If it's just a boolean the type inference might realize that a type is True or False even if it's inside a class, but you would still have the problem, that these types are shared among all users of the logger.
floitsch
floitsch 03/19/2025 11:30 AM
You could, however, have different loggers.
floitsch
floitsch 03/19/2025 11:30 AM
So it would then be log ::= lite-logging.DebugLogger.
But you don't need any constant-folding for that.
addshore
addshore 03/19/2025 11:34 AM
ooo, different loggers, with a null logger approach might work quite nicely
floitsch
floitsch 03/19/2025 11:35 AM
You could also just pass the log-level as argument to the Logger and then dispatch (factory constructor) in the logger.(edited)
👍1
addshore
addshore 03/19/2025 11:54 AM
As a version one, this is a slightly nice wrapper for my first use

import lite-logging log ::= lite-logging.new lite-logging.DEBUG-LEVEL main: log.debug: "Hello, world!"

and

import log as toit-log import .levels new level/int --name/string?=null-> Logger: return Logger level --name=name class Logger: logger /toit-log.Logger logger-level /int constructor .logger-level/int --name/string?=null: logger = toit-log.Logger (max toit-log.DEBUG-LEVEL logger-level) toit-log.DefaultTarget --name=name logger-level = logger-level log level/int [block] --tags/Map?=null -> none: if logger-level <= level: logger.log level block.call --tags=tags trace [block] --tags/Map?=null -> none: // Uses the debug level logger, as the toit logger has no trace level.. if logger-level <= TRACE-LEVEL: logger.log DEBUG-LEVEL "TRACE: $(block.call)" --tags=tags debug [block] --tags/Map?=null -> none: if logger-level <= DEBUG-LEVEL: logger.log DEBUG-LEVEL block.call --tags=tags info [block] --tags/Map?=null -> none: if logger-level <= INFO-LEVEL: logger.log INFO-LEVEL block.call --tags=tags warn [block] --tags/Map?=null -> none: if logger-level <= WARN-LEVEL: logger.log WARN-LEVEL block.call --tags=tags error [block] --tags/Map?=null -> none: if logger-level <= ERROR-LEVEL: logger.log ERROR-LEVEL block.call --tags=tags

Which means I can use blocks to avoid possibly expansive strings for debug logging, and leave the logging in place when the app is run in different logging modes.

It doesnt compile away the stuff that won't be used though. but solves my main pain, and doesnt look that bad at all
floitsch
floitsch 03/19/2025 11:55 AM
If the level of the logger can't be changed, you could have subclasses that don't have the if.
floitsch
floitsch 03/19/2025 11:55 AM
Not sure it's worth it.
floitsch
floitsch 03/19/2025 11:55 AM
More loggers also mean that the method dispatches become more expensive.
addshore
addshore 03/19/2025 11:56 AM
I'll try running with this for a bit, and see if I regret all of this in a few weeks :😉:
😁1
26 messages in total