No, you don’t get what I mean. SDL_Rect is just a rectangle,
without any semantics on its own.
You mis-stated that. You meant to say “it is just a data structure”
without any interpretation.
And, I want to apologise, I was annoyed by your comment
and was rude in my response. Sorry!
It’s up to the functions to define
its semantics. That’s why the issue is with the functions, not with
SDL_Rect.
Of course the issue is with the functions. But the abstract semantics
of a rectangle need to be stated SO that the concrete functions
implementing them do the right thing, and one can tell what’s wrong.
And the fact is SDL_Rect is a struct, as a value that means it has
4 implicitly defined projection functions, and that is probably wrong:
a rectangle is not isomorphhic to a 4-tuple.
That’s a basic problem but there’s not much you can do about
enforcing correct use in C.
I suppose I should explain in full ;(
-
Let A be an abstraction, and R be any set, then a function
repr: R → A
is called a representation of A.
-
Consider the collection of sets A of form:
r = { (x’,y’) | x <= x’ < x + w && y <= y’ < y + h }
for any integers x,y,w,h. We call such a collection of points a rectangle.
Note I included an empty rectangle!
-
Consider the collection R:
r = { (x,y,w,h) }
where x,y,w,h are any integers. This is called a 4-tuple.
-
Now, the semantics of a representation R → A are just a mapping
but we have to specify it.
-
Now we need a new concept: a structure preserving map.
Suppose we have some functions on A, for example:
intersect: A * A → A = A \intersect A
is an easy one, because the function is just the setwise intersection.
Then given a function:
INTERSECT: R * R -> R
the representation function repr is said to preserve structure if, and only if
intersect (repr a, repr b) = repr ( INTERSECT (a,b) )
A set A together with some such collection of functions like
intersect is called a structure in maths. The set R together with
functions like INTERSECT is also a structure. So now the notion
or representation is extended: a representation is a structure
preserving map from the model structure to the abstract structure.
Mathematicians also call this a functor, and the collections of
sets and functions are called categories.
Programmers sometimes call the representation an encoding.
Now, I HOPE you will agree that the intersection of two rectangles
in the abstract is what I specified above.
What we WANT then is two things:
(a) a model of a set of values R
(b) a representation function from R to A
and of course that representation must preserve structure.
This means the repr is NOT just mapping points from R to A,
it is also mapping functions as well:
repr: INTERSECT -> intersect
Now, the point is you are NOT free to just do anything you want.
“repr” has rules to obey! It has to be a function, and it has to be
structure preserving.
IF we choose
repr: SDL_Rect -> Rectangles
given by
x,y,w,h | --> { (x',y') | x <= x' < x + w && y <= y' < y + h }
we have a model of rectangles. Some values map to the same
rectangle, in fact the set:
(x,y,w,h | w <= 0 or h <=0 }
is the kernel of the representation (all the values map to the empty set),
and all other values of the representation map to a unique rectangle.
All non-empty rectangles also have a unique representation.
It is my guess these are the intended semantics.
Clearly the SDL_Blit function taking an SDL_Rect instead of a point is an error.
This is not something you can argue about! Its a FACT provable from the
representation. There is no unique left corner for an empty rectangle
(in the abstract) and there are many left corners for empty rectangles
modelled by an arbitrary SDL_Rect. So the results are indeterminate.
And as I mentioned I believe there’s a bug in the software renderer
here, where the code forgets to check for the null case, and uses
the h and w values as counters in a loop in such a way that the loop
counts off to the maximimum integer then wraps around and only terminates
-h and -w short of the start value.
There are other possible semantics. One is to allow negative h and w.
Another is to BAN non-positive h and w except in one case (0,0,0,0).
This is not so good in C because the invariant cannot be enforced
by the type system (an invariant is nothing more than a subset!)
It really doesn’t matter WHAT the representation is.
But it HAS to be specified because it is NOT obvious.
If a function “repr” is chosen mapping:
repr:SDL_Rect* -> Rectangles
[Where SDL_Rect* is some subset of SDL_Rect called the
representation invariant]
THEN we can check if it is structure preserving, in other words,
we can check if the C functions are correctly implemented,
given an abstract definition of the functions.
So this is what I meant by “the semantics of SDL_Rect”.
Yes, its specified by functions, in particular the repr function.
But that’s a mathematical function NOT a C function.
The C functions like SDL_Intersect are NOT models or
specifications, rather, given SDL_Intersect is intended to
represent the abstract intersection, there is a checkable
requirement on the implementation that it act to preserve
structure.
The semantics I have used above is called Denotational Semantics
which is gobbledgook for “modelling types as sets of values”.
The model here is concrete: I’m assuming a C struct is a tuple
of values and thus represents a set in an obvious way.
We can get more technical and model WITHOUT any sets at all,
but that’s category theory and is a bit beyond this mini-lecture :)On 27/08/2013, at 5:32 AM, Sik the hedgehog wrote:
–
john skaller
@john_skaller
http://felix-lang.org