HNHacker News
TopNewBestAskShowJobs

tinkersleep

132 karma · joined December 20, 2017

submissionscomments
tinkersleep··on Type-Safe Printf for C
You are right, it was a poor decision. The format is not C compatible, and using the same sigil is dangerous when switching and this library's format is passed to standard printf. This started out as a drop-in replacement, but it isn't, and cannot be. The library should not encourage, but avoid accidental format string mistakes.

So thank you, this is fixed.

tinkersleep··on Type-Safe Printf for C
OK, yes, good idea.
tinkersleep··on Type-Safe Printf for C
There is __VA_OPT__ in C++2a, which handles recursion termination in macro expansion. This will probably be in future C, too, right?

And if there was also __EVAL__ to force the macro preprocessor into another evaluation level, you could write recursive macros quite easily, e.g., to wrap every argument into a function call:

    #define EACH(f,x,...) f(x) __VA_OPT__(, __EVAL__(EACH(f, __VA_ARGS__)))
This would make the macro magic for this library trivial: you could process lists recursively.

Edit: added missing paren

tinkersleep··on Type-Safe Printf for C
Exactly! Or on Windows 64-bit, where 'long' is 32-bit and 'size_t' is 'unsigned long long'.
tinkersleep··on Type-Safe Printf for C
> - I wanted a form to register new types, so it could work for user-defined types;

Yes, I had the same urge. You can easily fall into the trap of too many features on the list. I settled on keeping user types out: you can always write a stringify() and pass that to the printf. Not the same, I know. But a more finite project.

> - the C pre-processor knows nothing about lists that can be expanded multiple times;

Yeah, that's a hack. Look at the 'VA_EXP()' macros in include/va_print/base.h. Ugly. Incomprehensible.

> - variadic C macros are ugly hacks.

Absolutely. But I think there is no other way in C.

> Actually, if the C pre-processor supported lists, it would be possible to implement RTTI in C.

I couldn't resist to put in '%t' which prints the C type of the argument...

tinkersleep··on Type-Safe Printf for C
Ok, thanks for the hint. I put the most important infos into the intro: you just don't need 'll', 'l', 'z' modifiers for specifying sizeof(operand), as the compiler does that via _Generic.
tinkersleep··on Type-Safe Printf for C
Probably the 1e6th approach, but anyway, I also wanted to play with this myself: here's a _Generic and macro based approach to get printf type-safe in C. It needs C11, and uses some gcc extensions.
tinkersleep··on Undefined medium – A free and open-source monospace typeface
A monospaced 8 bit pixel font I made is 'Liquid Mean', which also aims at Unicode (with some 2400 characters). But it is available only in a weird format as a C library or an private format text file. http://www.theiling.de/projects/liquid.html
tinkersleep··on Show HN: 100x Faster Slicing of SCAD Files for 3D Printing
Well, yes and no. If your slice at 0.1mm with Hob3l, then slic3r can still decide that it uses 0.2mm or 0.3mm or 0.4mm slices -- it would just skip a few slices from Hob3l. I don't think there is a problem with that. It will get weird if you use Hob3l with 0.2mm slices and then slic3r with 0.35mm slices -- this will cause Moire effects. It is not wrong, but may look interesting...
tinkersleep··on Show HN: 100x Faster Slicing of SCAD Files for 3D Printing
Author here. All the common stuff (that is based on 3D CSG without extensions) works fine, and most for 3D construction operators just produce a polyhedron with a simple algorithm (e.g., linear_extrude), so that's fine, too.

But some of the more advanced CGAL based operations for constructing 3D objects will not work in 2D, because they are inherently 3D and complex, e.g. 'hull', 'minkowski'.

tinkersleep··on Show HN: 100x Faster Slicing of SCAD Files for 3D Printing
Author here. Thank you for providing the file, I will debug it. I must admit that I spent almost no time to think about memory management, and my test files are way smaller. I guess this will be a debugging session. :-)
tinkersleep··on Regex Parser in C Using Continuation Passing
Thanks! It was fun tinkering.

For the regex problem, because of the required backtracking, data usage is definitely not O(1), so the continuation data will not be storable on the stack for an O(1) stack tail-call-only CPS version of regex. That context data for the continuations will need to go to the heap, and so we are basically back to how you'd avoid recursion to avoid unbounded stack: by using some data structures on the heap. And at that point, you could just use more straight-forward data structures than those needed for CPS here.

Anyway, the one-phase parsing+matching is still interesting, I think, and it is worth a try to get it to work in O(1) stack by storing the continuation data on the heap. So after fixing SIGSEGVs for infinite recursions, I will go back to fixing memory leaks. :-)

tinkersleep··on Regex Parser in C Using Continuation Passing
gcc generates 'jmp *%eax' (and other computed branch instructions) for this code, so yes, it uses tail-calls for function pointers.
tinkersleep··on Regex Parser in C Using Continuation Passing
You are absolutely right!

But I'd like to stress that this is a problem of this implementation, but not of the CPS technique as such: CPS is just not used to its extreme here to allow for tail-call optimisation of all functions, which would then result in O(1) stack usage.

The problem with this implementation is that gcc cannot tail-call optimise every function call, because continuation results are evaluated in the middle of the computation (e.g. for all 'or' decisions). This means the compiler cannot discard the old stack frame.

I should try harder and see what gcc can then do for me! :-)

tinkersleep··on Regex Parser in C Using Continuation Passing
Hmm, I have yet to see a trivial implementation for full-featured regex syntax, which was my goal.

The idea was not to parse a simple dialect of regex, but to parse a full-featured dialect, including things like \d, \), [)] and multi-level (), like (a|(b|c\)d[e)f])*g|h)+, so, e.g., the simple approach of scanning for the closing ) when you find a ( does not really work. Just for parsing such regexs this requires a recursive scanner, and then, a recursive data structure to store the result of parsing the regexp, and this runs counter to matching at the same time.

The linked code you provide assumes that you can first parse the whole pattern (like '(...)'), interpret that pattern, and then recurse to match it. There do not seem to be test cases in your code for the complex regexs cited above. So I don't think the approach of trivial recursion works with a full-featured standard regex grammar.