3D Rendering Engine (game engine)

Thanks for the tip on that lib. One of my goals however is to stick with pure Crystal as much as possible, however, I suppose I could cheat and port it later. We’ll see.

1 Like

I know quite well how WPF uses it. It has two passes: measure and then layout. you can use default measure method when it will call all its childrens’ measure() method recursively and it will return the space that they will be comfortable with, then based on settings on the layout pass it will tell them what top left position and max size they can assume and then render it without overflow or with rulers to show overflow.

What’s WPF?

WPF = Windows Presentation Foundation

You can read some details about the layout calculation here: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/layout

I ended up porting that Java implementation of a constraint algorithm to Crystal.
I still need to do some cleanup but it’s passing all the tests so I assume it’s working :smile:

Here’s the initial benchmark scores

I’ve barely any time at all on performance. I’m not exactly sure how many constraints the average GUI will need to calculate, so I’ll probably worry about performance once I start using it.

Here’s an example of the actual syntax.
image

As you can see, if you can do basic algebra you can build constraints. The library I ported had a ton of methods with lengthy names to do all of these operations. Ugly stuff like greater_than_or_equal_to(), etc. So I’m very pleased with the look of these overloaded operators.

I should also point out that I added some overloaded operators to the base Number class as well. So you can place scalar values on the left hand side too! e.g. 20 == x or 20 >= x + y etc.

Here’s the source code https://github.com/neutrinog/kiwi-crystal

2 Likes

@da1nerd I’m not sure if you know, but annotating defs with @[Raises] is not needed. That applies mostly to fun.

Overriding operators leads usually to nice DSLs definitely. As long as there is no need to override some operators that can’t be overriden like || or && you are good.

Another approach to do that is to exponse use macro to traverse the DSL and translate to the appropiate entities. That would allow “overriding” any operator and the type can be checked against normal semantics. I haven’t come around yet to a way of introducing free variables nicely. But I wanted to share another path to accomplish the x + 2 == y + 10.

I’m not exactly following. Can you point me to an example of a macro based DSL?

I don’t have an implementation yet. I started the idea while playing around with z3 and prolog

Since overriding ^ is doable one can use it as

x = ctx.mk_bool_var("x")
y = ctx.mk_bool_var("y")
solver.assert(x ^ y)

But that won’t work with ||: x || y has fixed semantics on the compiler, yet it make sense in z3 formulas also.

So I though of going in the route of

Z3.build ctx, ->(x : Bool, y : Bool) {
  x || y
}

The Z3.build macro could transform the Crystal AST of the proc to a series of mk_bool_var and other instructions to create the Z3 equivalent expression. But at the same time it can use typeof over the proc expression to ensure the typing (in Crystal) of the proc make sense, even though it will never be called (nor compiled). Ref: https://github.com/bcardiff/crystal-z3/blob/master/playground/foo.cr

The way to introduce free variables is not that nice, but the goal was to avoid the issue of some operators not been overridable.

Another (probably outdated) example is in https://github.com/bcardiff/crolog/blob/master/src/crolog/macros/rule.cr where a macro is used to generate the appropiate functions for prolog.

1 Like

That’s an interesting idea. I don’t think I’ll need to go that far though (at least for now) because I only need a small set of operators. +, -, >=, <=, *, ==.

And there’s always the possibility to use .or, .and or even .| and .& which are overloadable.