Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Extendable structure with inspection

301 views
Skip to first unread message

humptydumpty

unread,
Jun 2, 2015, 4:29:09 PM6/2/15
to
Hi!

Without more words this content of 'struct.fs' + tests.
Verified under GForth 0.7.3, excerpt from command-line:

---
$ gforth -e "include struct.fs"

\ Extendable structure with inspection. Wordlist based.
\ USAGE: see code between [IF] [THEN]
\ -----
\ CONS: not a fastest compiling time
\ PROS: could use information at compile-time to compile for a faster execution
\ GForth 0.7.3 tested.

\ Cure for improbable redefinition of '+' between
\ define structure locus and locus of fields use
VOCABULARY UNTAINTED
get-current ALSO UNTAINTED DEFINITIONS
' + alias +
set-current PREVIOUS

WARNINGS OFF
\ This text-macro is 'Base' dependent. Field compiled by this macro
\ should be used inside scope of a defined structure. See 'struct' definition.
: field ( offs size -- offs+size ; Text based macro )
over >R
: R> ?dup
IF
S>D <# [CHAR] + hold BL hold #S #>
postpone SLITERAL postpone EVALUATE
THEN
postpone ; IMMEDIATE +
;
\ For a safe use of fields defined by text-macro 'field',
\ preserve 'Base' that exists at time of structure definition.
\ Also cures "funny" '+' redefinitions.
: struct
get-current wordlist
dup CREATE , base @ , IMMEDIATE set-current 0 ( old-wid 0 )
( Now compile fields in structure-wordlist )
DOES>
Base @ >R
dup cell+ @ Base !
@ >order ALSO UNTAINTED
parse-name ['] evaluate
CATCH
PREVIOUS previous R> Base !
THROW
;
: end-struct ( old-wid size -- )
S" VALUE SIZE" evaluate
set-current
;
WARNINGS ON

: extend ( "struct-name" -- old-base old-wid )
Base @ get-current
' >BODY dup
@ dup set-current >order
cell+ @ Base !
;
: end-extension ( old-base old-wid -- )
set-current previous Base !
;

: fields-of ( "struct-name -- ; structure inspection word)
' >BODY @ wordlist-words
;

-1 [IF] sh cat struct.fs
HEX \ Test for independence of 'Base'
struct POS
cell field X
cell field Y
end-struct
DECIMAL

cr ." Test for funny '+' redefinition: "
: + ." funny " + ;

cr ." Test for inspection:"
cr ." POS constituents: " fields-of POS

cr ." Test for scoping of defined structure at interpret/compile-time and fields compiling:"
VARIABLE X 1 X !
CREATE Ob POS SIZE allot
99 Ob POS X !
101 Ob POS Y !

: testX Ob POS X ? X ? ;
: testY [ Ob POS Y ]L ? X ? ;
: 2testY Ob POS Y ? X ? ;
see testX see testY see 2testY
cr testX cr testY cr 2testY

cr ." Test for extending structure:"
extend POS
SIZE
cell field Z
TO SIZE
end-extension

cr ." New POS constituents:" fields-of POS

Create Ob2 POS SIZE allot
2013 Ob2 POS X !
2014 Ob2 POS Y !
2015 Ob2 POS Z !
: testZ Ob2 dup POS X ? dup POS Y ? POS Z ? ;
see testZ
cr testZ

cr .s cr bye
[THEN]


Test for funny '+' redefinition: redefined +
Test for inspection:
POS constituents:
SIZE Y X
Test for scoping of defined structure at interpret/compile-time and fields compiling:
: testX
Ob ? X ? ;
: testY
34389371752 ? X ? ;
: 2testY
Ob 8 + ? X ? ;
99 1
101 1
101 1
Test for extending structure:
New POS constituents:
Z SIZE Y X
: testZ
Ob2 dup ? dup 8 + ? 16 + ? ;
2013 2014 2015
<0>
$
---

Have a nice day,
humptydumpty

Anton Ertl

unread,
Jun 3, 2015, 2:23:53 AM6/3/15
to
humptydumpty <oua...@gmail.com> writes:
>HEX \ Test for independence of 'Base'
>struct POS
> cell field X
> cell field Y
>end-struct
>DECIMAL

This does not test independence of BASE, because "4" or "8" are the
same in HEX and DECIMAL, and no bigger numbers are occuring here.

Your fix for the "+" lookup issue looks good, and should work also for
the case when the FORTH-WORDLIST is not in the search order.

However, I found a hole in your BASE workaround:

HEX
struct POS
DECIMAL
10 cells field X
5 cells field Y
end-struct

0 POS Y 10 cells = . \ should be true, but isn't.

That's fixable, but it shows that using EVALUATE is tricky.

BTW, I think the word you mean is "introspection", although I am not
sure that it is appropriate here, either.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2015: http://www.mpeforth.com/euroforth2015/euroforth2015.htm

humptydumpty

unread,
Jun 3, 2015, 11:27:32 AM6/3/15
to
miercuri, 3 iunie 2015, 09:23:53 UTC+3, Anton Ertl a scris:
Hi!

I meant 'introspection'. Please substitute 'inspection' with
'introspection' in that my previous post. Don't know where was
my mind when I posted...
Thanks.

I'm on 8 bytes cell forth, and at end 'Z' field has decimal offset 16,
and it behaves right.

I think that version is quite usable as it is and
I'll postpone next revision of structures, as my initial goal was done:
to prove that 'forth' can use information at compile-time
to inline fields and fields could be made visible only in
scope of a parent structure.

Everyone could use that version of structures at their hart wish,
add methods, etc...

humptydumpty

unread,
Jun 3, 2015, 2:30:24 PM6/3/15
to
Hi!

Healthier version, at previous version I forgot cure 'VALUE'
for redefinition:

---
$ gforth -e "include struct.fs"

\ Extendable structure with introspection. Wordlist based.
\ USAGE: see code between [IF] [THEN]
\ -----
\ CONS: not a fastest compiling time
\ PROS: could use information at compile-time to compile for a faster execution
\ GForth 0.7.3 tested.

\ Cure for redefinition of Forth words
VOCABULARY UNTAINTED
get-current ALSO UNTAINTED DEFINITIONS
' + alias +
' VALUE alias VALUE
set-current PREVIOUS

WARNINGS OFF
\ This text-macro is 'Base' dependent. Field compiled by this macro
\ should be used inside scope of a defined structure. See 'struct' definition.
: field ( offs size -- offs+size ; Text based macro )
over >R
: R> ?dup
IF
S>D <# [CHAR] + hold BL hold #S #>
postpone SLITERAL postpone EVALUATE
THEN
postpone ; IMMEDIATE +
;
\ For a safe use of fields defined by text-macro 'field',
\ preserve 'Base' that exists at time of structure definition.
\ Also cures "funny" '+' redefinitions.
: struct
get-current wordlist
dup CREATE , base @ , IMMEDIATE set-current 0 ( old-wid 0 )
ALSO UNTAINTED
( Now compile fields in structure-wordlist )
DOES>
Base @ >R
dup cell+ @ Base !
@ >order ALSO UNTAINTED
parse-name ['] evaluate
CATCH
PREVIOUS previous R> Base !
THROW
;
: end-struct ( old-wid size -- )
S" VALUE SIZE" evaluate
PREVIOUS set-current
;
WARNINGS ON

: extend ( "struct-name" -- old-base old-wid )
Base @ get-current
' >BODY dup
@ dup set-current >order
cell+ @ Base !
;
: end-extension ( old-base old-wid -- )
set-current previous Base !
;

: fields-of ( "struct-name -- ; structure inspection word)
' >BODY @ wordlist-words
;

-1 [IF] sh cat struct.fs

cr ." Test for funny redefinition of 'VALUE': " : VALUE ." WHAT A FUNNY VALUE!" ;
3 Base ! \ Test for independence of 'Base'
Test for funny redefinition of 'VALUE': redefined Value with VALUE
Test for funny '+' redefinition: redefined +
Test for inspection:
POS constituents:
SIZE Y X
Test for scoping of defined structure at interpret/compile-time and fields compiling:
: testX
Ob ? X ? ;
: testY
34389371968 ? X ? ;
: 2testY
Ob 8 + ? X ? ;
99 1
101 1
101 1
Test for extending structure:
New POS constituents:
Z SIZE Y X
: testZ
Ob2 dup ? dup 8 + ? 16 + ? ;
2013 2014 2015
<0>
$
---

Thanks to Anton Ertl for his insightful comments
here on c.l.f., during development time of this
structure lexicon.

Raimond Dragomir

unread,
Jun 3, 2015, 11:54:11 PM6/3/15
to
What did you accomplished? You still need the structure name (not the
object name) to associate the following field with it.
You need to do this: Ob POS X
A much cleaner and simpler way is just to prefix the field names with the
structure name! For example: Ob POS.X or Ob POS->X or anything you like.

I would have been impressed if you was able to do that:
Ob X

This was the real discussion in some other thread: associate the field of
the structure with the object!

Alex McDonald

unread,
Jun 4, 2015, 4:11:20 AM6/4/15
to
on 04/06/2015 04:54:11, Raimond Dragomir wrote:

>
> What did you accomplished? You still need the structure name (not the
> object name) to associate the following field with it.
> You need to do this: Ob POS X
> A much cleaner and simpler way is just to prefix the field names with
> the structure name! For example: Ob POS.X or Ob POS->X or anything you
> like.
>
> I would have been impressed if you was able to do that:
> Ob X
>
> This was the real discussion in some other thread: associate the field
> of the structure with the object!
>
>

OBJECT POS X suggests that OBJECT really isn't an object at all; it's an
area of memory over which the structure POS is being applied to get the
variable at offset X. I'm not quite sure whay you would want OBJECT X in
such a case. For most uses, defining and knowing the offset of X is
rather pointless since the class (and any objects derived from it)
encapsulates the variable. Althought there are similarities, structures
and classes are not necessarily the same, and classes may not always be
supersets of structures.

Raimond Dragomir

unread,
Jun 4, 2015, 7:43:02 AM6/4/15
to
I never mentioned classes. Only (simple) structures. I name "object" an
entity wich is materialized in memory in some quantity. A variable is an object. An address or an offset isn't an object. So, a structure is a "type"
which defines some offsets, that's all.
But it's against the Forth philosophy to declare "types" or worse, to
bind "types" to objects. That's why in forth variables provide their address,
and in fact everything provides their address. That's why we have explicit @,
!, etc.
VALUE and frieds are against Forth philosophy.
I admit that in my dialect I use TO to local variables (only) but my ' (tick)
is able to provide the address of a local, so I can @, c@, ! etc even on locals.

Alex McDonald

unread,
Jun 4, 2015, 3:22:01 PM6/4/15
to
Hmmmm.

> But it's against the Forth philosophy to declare "types" or worse, to
> bind "types" to objects. That's why in forth variables provide their
> address, and in fact everything provides their address. That's why we
> have explicit @, !, etc.
> VALUE and frieds are against Forth philosophy.
> I admit that in my dialect I use TO to local variables (only) but my '
> (tick) is able to provide the address of a local, so I can @, c@, !
> etc even on locals.
>
>

I'd rather see you argue why you have this opinion, based on some
experience. Packaging your opinion as "Forth philosophy" doesn't really
help.



Raimond Dragomir

unread,
Jun 5, 2015, 2:23:25 AM6/5/15
to
> I'd rather see you argue why you have this opinion, based on some
> experience. Packaging your opinion as "Forth philosophy" doesn't really
> help.

I have this opinion based on my personal experience with Forth. If I like
something in Forth I say it, if I don't like something else I also say it.
I don't repeat anything from anyone else's opinions or what I read here or on internet.
And I don't feel the need to excuse myself every two or three words with "IMO"
and such things.
If what I say really helps someone, I don't know.

Rod Pemberton

unread,
Jun 5, 2015, 3:40:20 AM6/5/15
to
On Fri, 05 Jun 2015 02:23:24 -0400, Raimond Dragomir
<raimond....@gmail.com> wrote:

> If what I say really helps someone, I don't know.

It might. It might not. Why hold back?
You can always state something differently.

Why are your Forth experiences any less valid or
correct than Alex's, or Hugh's, or Ms. Rather's,
or whomever?

How is having to defend yourself from Alex any
better than not making excuses?


Rod Pemberton

--
If fewer guns reduced murders, how does one explain
Moscow, Chicago, New York, and South Africa?

humptydumpty

unread,
Jun 5, 2015, 3:40:28 AM6/5/15
to
Addressed your complaints:

1. You rants here that fields are global:
>C structs are powerful, the fields are associated with the object. In forth
>you cannot have this, fields are global. Forth structs are not so powerful.

2. In the same post you rant about inefficiency:
>This is a classical example of inefficiency (like also the CONSTANT example implemented with create does>). The field word will do @ + at RUNTIME even if the offsets are well known at compile time, and this is a very common situation!.

3. You don't see how to use wordlists to make fields local.


> You still need the structure name (not the
> object name) to associate the following field with it.
> You need to do this: Ob POS X

Do you really understand what 'POS' is and what 'X' is?

> A much cleaner and simpler way is just to prefix the field names with the
> structure name! For example: Ob POS.X or Ob POS->X or anything you like.
>

So you want to revert to global field names that you previously criticized. :-)

> I would have been impressed if you was able to do that:
> Ob X
Should I? LOL

> This was the real discussion in some other thread: associate the field of
> the structure with the object!
Not only!

Alex McDonald

unread,
Jun 5, 2015, 10:31:01 AM6/5/15
to
OK, but I asked you to explain, not to indulge in an unnecessary personal
justification.

You said (from the bit snipped earlier)

<quote>
I never mentioned classes. Only (simple) structures. I name "object" an
entity wich is materialized in memory in some quantity. A variable is an
object. An address or an offset isn't an object. So, a structure is a
"type" which defines some offsets, that's all. But it's against the Forth
philosophy to declare "types" or worse, to bind "types" to objects.
</quote>

A variable is an object, but an address isn't an object? Since a variable
is a named address, I don't understand what you mean.

How does a collection of offsets in a structure make the structure a
type? Type checking is where the compiler (although this might be done at
run time) says "You can't do that operation Y on this type X". Structures
and structure variables/offsets in Forth don't do that, and there's no
"binding to objects" going on.

This isn't about "Forth philosophy" (whatever that is) at all. I'm not
attacking you here, I'm looking to understand.

Raimond Dragomir

unread,
Jun 5, 2015, 11:48:10 AM6/5/15
to
vineri, 5 iunie 2015, 17:31:01 UTC+3, Alex McDonald a scris:
> on 05/06/2015 07:23:22, Raimond Dragomir wrote:
> >> I'd rather see you argue why you have this opinion, based on some
> >> experience. Packaging your opinion as "Forth philosophy" doesn't really
> >> help.
> >
> > I have this opinion based on my personal experience with Forth. If I
> > like something in Forth I say it, if I don't like something else I
> > also say it. I don't repeat anything from anyone else's opinions or
> > what I read here or on internet. And I don't feel the need to excuse
> > myself every two or three words with "IMO" and such things.
> > If what I say really helps someone, I don't know.
> >
>
> OK, but I asked you to explain, not to indulge in an unnecessary personal
> justification.
>
> You said (from the bit snipped earlier)
>
> <quote>
> I never mentioned classes. Only (simple) structures. I name "object" an
> entity wich is materialized in memory in some quantity. A variable is an
> object. An address or an offset isn't an object. So, a structure is a
> "type" which defines some offsets, that's all. But it's against the Forth
> philosophy to declare "types" or worse, to bind "types" to objects.
> </quote>
>
> A variable is an object, but an address isn't an object? Since a variable
> is a named address, I don't understand what you mean.
>
A variable is not a named address, it is a quantity in memory. It is
"allocated". I don't know how to explain it more... Lets take a forth
example:
create X
variable Y ( or create Y 1 cells allot )

X is an address. It is just an attribute of something (we don't know
what something is because we don't know it's size in the first place.
The size is zero, so the "object" doesn't exists). The name is another
attribute. Ok, the address and the name are related, associated, but
the object doesn't exist.
Y is an object. It exists because it occupies 4 bytes in memory. It's
address is just it's attribute. It's name is another attribute.

Types are attributes. They are associated with objects, that's the purpose
of types. A type that is only declared and not associated with any object
is just useless. And a type is not an address, it is at least a quantity
(size) and can possibly define some other behavioral aspects of the object.

Structures which defines named offsets are types, because they specify
a quantity (the offset is not an address, it's a size). They don't produce
any effects if they are not "applied" to some object.

Now, for the forth "philosophy": you (not you, a generic programmer) are
supposed to apply manually types over "generic" objects - in fact raw
memory. The compiler is not supposed to know that a variable is x bytes
or some field of an object is y bytes. That's why we need to @ or c@ or !
explicitly. You are allowed to allocate memory (creating "objects") but
all the "types" are in your head, the compiler has no clue about that.
For being such an ignorant compiler, it cannot provide anything else for
an "object" but it's address. In fact it doesn't know anything else: it
maps the name with the address, you give the name it gives the address
But the address it provides is not an object. You may say it is, because
in the end there must be something at that address... Well, it may be
or it may be not:
create x
create y
create z 1 cells allot

It is possible in forth isn't it? x y and z cannot be objects because they
occupy the same pysical space at the same time... Pretty impossible
with our laws of nature :)


> How does a collection of offsets in a structure make the structure a
> type? Type checking is where the compiler (although this might be done at
> run time) says "You can't do that operation Y on this type X". Structures
> and structure variables/offsets in Forth don't do that, and there's no
> "binding to objects" going on.
>
> This isn't about "Forth philosophy" (whatever that is) at all. I'm not
> attacking you here, I'm looking to understand.

That's why we can't have real types (in fact real objects) in forth, because
that's against it's philosophy - against it's "nature".
People wanted something more like a C variable with a clear "type", so
we have VALUE in forth. I don't know - for example - after many years of
forth usage why (or when) I should use VALUEs. It's a matter of personal
preference? It saves me a @ that's all? The result is that I never used
VALUEs.
Speaking of that, let's think, if the forth had had only VALUEs from the start,
how would it look like? How about byte variables (probably CVALUEs) how
about structures, how about arrays? arrays of structures? Do you think it
would have been even possible? Without a rigid syntax like C?
That's what I'm thinking about when I speak about the forth philosophy.

Alex McDonald

unread,
Jun 5, 2015, 1:10:55 PM6/5/15
to
That is a distinction of no difference. Otherwise you would be able to
write some code that told me how many bytes Z addressed when treated as
an object.

CREATE Z 256 ALLOT

You would also be able to tell me the difference between X and Y

CREATE X
X CONSTANT Y

Would you have Y as an object, but X as "not existing"?

>
> Types are attributes. They are associated with objects, that's the
> purpose of types. A type that is only declared and not associated with
> any object is just useless. And a type is not an address, it is at
> least a quantity (size) and can possibly define some other behavioral
> aspects of the object.

I agree with only a small part of that.

>
> Structures which defines named offsets are types, because they specify
> a quantity (the offset is not an address, it's a size). They don't
> produce any effects if they are not "applied" to some object.

No, it's an offset. You cannot write code to tell the size of HOWBIG in
this structure:

begin-structure s
field: X
field: Y
field: HOWBIG
end-structure

It's at an offset of 2 cells, that's all we know. It's identical to this:

begin-structure s
field: X
field: Y
0 field+ HOWBIG
end-structure

i.e. the length or size is completely undefined and unknowable.

Forth structures, variables, creates and so on define types by letting
the programmer use their addresses in specific ways; as CHARs, CELLs or
FLOATs for instance.

>
> Now, for the forth "philosophy": you (not you, a generic programmer)
> are supposed to apply manually types over "generic" objects - in fact
> raw memory. The compiler is not supposed to know that a variable is x
> bytes or some field of an object is y bytes. That's why we need to @
> or c@ or ! explicitly. You are allowed to allocate memory (creating
> "objects") but all the "types" are in your head, the compiler has no
> clue about that. For being such an ignorant compiler, it cannot
> provide anything else for an "object" but it's address. In fact it
> doesn't know anything else: it maps the name with the address, you
> give the name it gives the address But the address it provides is not
> an object. You may say it is, because in the end there must be
> something at that address... Well, it may be or it may be not:
> create x
> create y
> create z 1 cells allot
>
> It is possible in forth isn't it? x y and z cannot be objects because
> they occupy the same pysical space at the same time... Pretty
> impossible with our laws of nature :)

Apart from the problem that X Y and Z in your example will very likely be
different addresses in most Forths, there is absolutely nothing stopping
two or more names resolving to the same address.

CREATE X CELL ALLOT
SYNONYM Y X
SYNONYM Z X
10 X ! Z @ . 20 Y ! X @ . Z @ .

>
>
>> How does a collection of offsets in a structure make the structure a
>> type? Type checking is where the compiler (although this might be done at
>> run time) says "You can't do that operation Y on this type X". Structures
>> and structure variables/offsets in Forth don't do that, and there's no
>> "binding to objects" going on.
>>
>> This isn't about "Forth philosophy" (whatever that is) at all. I'm not
>> attacking you here, I'm looking to understand.
>
> That's why we can't have real types (in fact real objects) in forth,
> because that's against it's philosophy - against it's "nature".

Nonsense. It's a programming language, not a moral imperative.

> People wanted something more like a C variable with a clear "type", so
> we have VALUE in forth. I don't know - for example - after many years
> of forth usage why (or when) I should use VALUEs. It's a matter of
> personal preference? It saves me a @ that's all? The result is that I
> never used VALUEs.

That's fine.

> Speaking of that, let's think, if the forth had had only VALUEs from
> the start, how would it look like? How about byte variables (probably
> CVALUEs) how about structures, how about arrays? arrays of structures?
> Do you think it would have been even possible? Without a rigid syntax
> like C? That's what I'm thinking about when I speak about the forth
> philosophy.

Even with values, all this is possible. A value is simply a name that
returns a number, and that number can be an address.


Elizabeth D. Rather

unread,
Jun 5, 2015, 1:53:03 PM6/5/15
to
That's entirely fair, but generalizing your opinion as "Forth
philosophy" is going a bit far.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

hughag...@gmail.com

unread,
Jun 5, 2015, 8:34:08 PM6/5/15
to
On Friday, June 5, 2015 at 10:53:03 AM UTC-7, Elizabeth D. Rather wrote:
> On 6/4/15 8:23 PM, Raimond Dragomir wrote:
> >> I'd rather see you argue why you have this opinion, based on some
> >> experience. Packaging your opinion as "Forth philosophy" doesn't really
> >> help.
> >
> > I have this opinion based on my personal experience with Forth. If I like
> > something in Forth I say it, if I don't like something else I also say it.
> > I don't repeat anything from anyone else's opinions or what I read here or on internet.
> > And I don't feel the need to excuse myself every two or three words with "IMO"
> > and such things.
> > If what I say really helps someone, I don't know.

> That's entirely fair, but generalizing your opinion as "Forth
> philosophy" is going a bit far.

Oh, you're the only person who is allowed to do that?

At least Raimond actually has some programming experience to back up his opinions --- you don't have any programming experience (other than COBOL) to back up your opinions, but yet you routinely spout drivel and declare it to be Forth philosophy.

This thread is about structs. None of the Forth Inc. books discussed structs at all. SwiftForth doesn't provide FIELD. The data comma'd after a CREATE for use by the DOES> code is effectively a struct, but you don't seem to know that the fields can have names rather than just numeric offsets (none of the Forth Inc. books used named fields but they typically use CELL+ to step through the fields). Also, CREATE DOES> is the only example of packaged data that your books provide, yet these can't be nodes in a data-structure because CREATE only builds one at a time and gives it a name like an overgrown variable. There is no evidence anywhere to indicate that you know what a struct is or know that structs can be linked together by pointers to form a data-structure. You routinely describe PAD as the standard for temporary storage, and there is no evidence to indicate that you know what a heap is (although SwiftForth does have a heap).

The only data-structure that "Starting Forth" provided was the array, and it wasn't general-purpose because it had to be rewritten with cut-and-paste programming for every primitive data-type (chars and words were provided in the book). In all likelihood, this represented your entire knowledge of data-structures in 1983 --- and you haven't learned anything since then, either.

hughag...@gmail.com

unread,
Jun 5, 2015, 8:53:19 PM6/5/15
to
On Friday, June 5, 2015 at 8:48:10 AM UTC-7, Raimond Dragomir wrote:
> Types are attributes. They are associated with objects, that's the purpose
> of types. A type that is only declared and not associated with any object
> is just useless. And a type is not an address, it is at least a quantity
> (size) and can possibly define some other behavioral aspects of the object.
>
> Structures which defines named offsets are types, because they specify
> a quantity (the offset is not an address, it's a size). They don't produce
> any effects if they are not "applied" to some object.

I wrote an RfD for Forth-200x asking that we have a word that, given the address of a memory-block in the heap, returns its size. This seemed super-easy to me, because the information is already stored (FREE and RESIZE access this information to do what they do). Everybody seemed to like the idea, but then Leon Wagner killed it by saying that he wouldn't implement this in SwiftForth and he didn't understand what it was for.

I rewrote ALLOCATE in the novice-package to store the size of the memory-block underneath it (redundant because it is already being stored internally, but I don't have access to the information so I have to manually store it). I also provided the word ALLOCATION that, given the address of a memory-block in the heap, returns its size. ALLOCATION is needed by CLONE-NODE that clones a node in a data-structure without knowing at compile-time what data-type (or what size) the node is.

I also rewrote FREE and RESIZE so that they would only operate on memory-blocks in the heap, but would quietly do nothing if given memory-blocks in the dictionary. This allows me to either generate a data-structure at compile-time in the dictionary or at run-time in the heap, and have all the words that work on the data-structure be the same either way (I can switch back and forth without needing to rewrite the code that works with the data-structure).

All of this is fundamental to my style of OOP in the novice-package. It is also grossly inefficient because it is written in ANS-Forth --- such low-level code as ALLOCATE FREE and RESIZE should be written in assembly-language for efficiency.

> Now, for the forth "philosophy": you (not you, a generic programmer) are
> supposed to apply manually types over "generic" objects - in fact raw
> memory. The compiler is not supposed to know that a variable is x bytes
> or some field of an object is y bytes. That's why we need to @ or c@ or !
> explicitly. You are allowed to allocate memory (creating "objects") but
> all the "types" are in your head, the compiler has no clue about that.
> For being such an ignorant compiler, it cannot provide anything else for
> an "object" but it's address. In fact it doesn't know anything else: it
> maps the name with the address, you give the name it gives the address
> But the address it provides is not an object. You may say it is, because
> in the end there must be something at that address... Well, it may be
> or it may be not:
> create x
> create y
> create z 1 cells allot
>
> It is possible in forth isn't it? x y and z cannot be objects because they
> occupy the same pysical space at the same time... Pretty impossible
> with our laws of nature :)

Another thing that I think should be standardized, is that code and data are separate. In this case, your X Y and Z would be the same address. If code and data are jumbled together, as in ANS-Forth, then the header for Y will be on top of X's data and the header for Z on top of Y's data.

In ANS-Forth, code and data are jumbled together --- this is utterly stupid! --- this is actually one of the most blatant examples of Elizabeth Rather's blithering ignorance of even the most basic computer-programming concepts.

Albert van der Horst

unread,
Jun 6, 2015, 6:46:48 AM6/6/15
to
In article <mksl4j$pm6$1...@dont-email.me>,
Now that we have mini-oofs, I don't use that kind of coding anymore.
Instead I define getters and setters working on the same offset (field
so you want)

An example: Farey sequence in a recent euler problem.
(In my system the offsets are generated by , and allot, _ is a don't
care value)
[A Farey vector is a direction in a grid, Pnt[] is the point of this
exercise: the position of a point on a line going through Start in
that direction]

class Farey
M: Fprev! 2! M;
M: Fprev@ 2@ M;
M: Fpy @ M; _ , \ Idem y
M: Fpx @ M; _ , \ Old Farey Direction X

M: Fcur! 2! M;
M: Fcur@ 2@ M;
M: Fy @ M; _ , \ Idem y
M: Fx @ M; _ , \ Farey Direction X

M: delta! 2! M;
M: deltay @ M; _ ,
M: deltax @ M; _ , \ Increment going to next Farey line.

M: Start! 2! M;
M: Pnt[] OVER Fy * OVER @ + >R CELL+ @ SWAP Fx * + R> M; ( index -- x[i],y[i])
M: Ys @ M; _ ,
M: Xs @ M; _ , \ leftmost raster point on line

M: End! 2! M;
M: Ye @ M; _ ,
M: Xe @ M; _ , \ rightmost raster point on line

M: #unoccupied M; _ , \ Above - not on - line.
M: #points M; _ , \ Raster points one line.
endclass

You see that most methods are getters (Fx gives the x-component
of a Farey direction etc.) Most setters only make sense in pairs,
so Fcur! is ( x,y --) . There is no way to get at the field behind
Fpx and the class serves to document that the program will not
do that.

The only old fashioned fields are #unoccupied and #points.

(I hope that this will not inspire someone to come up with
TO-fields.)

There is just one object of this class, so all this could've been just
plain variables and colon definitions. 1)

Like so:

2variable Fprev
: Fprev! Fprev 2!
: Fpy Fprev @ ;
: Fpx Fprev CELL+ @ ;
HIDE Fprev ( To make it totally equivalent)
...
2variable Start
..
( index -- x[i],y[i])
: Pnt[] Start OVER Fy * OVER @ + >R CELL+ @ SWAP Fx * + R> ;

Somehow I find this usage of OO very helpful.
I would never have come up with plain code in that style.

Groetjes Albert

1) For some reason some people would call that a singleton.
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Albert van der Horst

unread,
Jun 6, 2015, 6:56:46 AM6/6/15
to
In article <8021c02c-0a0c-42ef...@googlegroups.com>,
<hughag...@gmail.com> wrote:
>On Friday, June 5, 2015 at 8:48:10 AM UTC-7, Raimond Dragomir wrote:
>> Types are attributes. They are associated with objects, that's the purpose
>> of types. A type that is only declared and not associated with any object
>> is just useless. And a type is not an address, it is at least a quantity
>> (size) and can possibly define some other behavioral aspects of the object.
>>
>> Structures which defines named offsets are types, because they specify
>> a quantity (the offset is not an address, it's a size). They don't produce
>> any effects if they are not "applied" to some object.
>
>I wrote an RfD for Forth-200x asking that we have a word that, given the
>address of a memory-block in the heap, returns its size. This seemed
>super-easy to me, because the information is already stored (FREE and
>RESIZE access this information to do what they do). Everybody seemed to
>like the idea, but then Leon Wagner killed it by saying that he wouldn't
>implement this in SwiftForth and he didn't understand what it was for.

In doing so you revealed a problem with the current standardisation
process. I could easily add a size to my implementation of the allocation
wordset, and maybe some others. It is certainly useful.
So we would like to have the word reserved so that wherever it is used
at least it would mean the same. I appreciate that it is prohibitively
expensive to supply in a c-based Forth because malloc() can't handle this.

But the above means that it will not be standardised as say a controlled
word because those systems would have to admit that they can't implement
it. "We implement the total of the Forth language" would no longer be
true. So SIZE is kept out of the standard, and although you and I implement
the same word, its name would be different.

Groetjes Albert

Anton Ertl

unread,
Jun 6, 2015, 12:18:59 PM6/6/15
to
alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
>In article <8021c02c-0a0c-42ef...@googlegroups.com>,
> <hughag...@gmail.com> wrote:
>>I wrote an RfD for Forth-200x asking that we have a word that, given the
>>address of a memory-block in the heap, returns its size. This seemed
>>super-easy to me, because the information is already stored (FREE and
>>RESIZE access this information to do what they do). Everybody seemed to
>>like the idea, but then Leon Wagner killed it by saying that he wouldn't
>>implement this in SwiftForth and he didn't understand what it was for.

The SIZE RfD is still listed among the RfDs without CfVs. I guess we
should do some timeout of RfDs after some time, though.

>In doing so you revealed a problem with the current standardisation
>process. I could easily add a size to my implementation of the allocation
>wordset, and maybe some others. It is certainly useful.
>So we would like to have the word reserved so that wherever it is used
>at least it would mean the same. I appreciate that it is prohibitively
>expensive to supply in a c-based Forth because malloc() can't handle this.

It's not prohibitive, but not so cheap that one does add it without
first seeing the need demonstrated. What I found surprising is that
it's not just C-based Forths that use the system's malloc() to
implement ALLOCATE. So it's not just a few systems that would incur
the considerable cost, but pretty much all of them.

>But the above means that it will not be standardised as say a controlled
>word because those systems would have to admit that they can't implement
>it. "We implement the total of the Forth language" would no longer be
>true. So SIZE is kept out of the standard, and although you and I implement
>the same word, its name would be different.

Why would it be different? If you and Hugh cannot agree on a name
(and probably not on a common specification, either), that's certainly
not the fault of the standardization process; on the contrary, it
would explain why there is no progress in standardizing this feature.

hughag...@gmail.com

unread,
Jun 6, 2015, 10:35:22 PM6/6/15
to
On Saturday, June 6, 2015 at 9:18:59 AM UTC-7, Anton Ertl wrote:
> alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
> >In article <8021c02c-0a0c-42ef...@googlegroups.com>,
> > <hughag...@gmail.com> wrote:
> >>I wrote an RfD for Forth-200x asking that we have a word that, given the
> >>address of a memory-block in the heap, returns its size. This seemed
> >>super-easy to me, because the information is already stored (FREE and
> >>RESIZE access this information to do what they do). Everybody seemed to
> >>like the idea, but then Leon Wagner killed it by saying that he wouldn't
> >>implement this in SwiftForth and he didn't understand what it was for.
>
> The SIZE RfD is still listed among the RfDs without CfVs. I guess we
> should do some timeout of RfDs after some time, though.

There is no need for an RfD to time-out --- there can be no further discussion after Leon kills an RfD, because Forth Inc. owns Forth-200x. The following is how Leon Wagner killed the RfD. Notice how he is unaware of the sizeof operator in C++, and also unaware that objects can be copied when their type is not known at run-time (the type was declared at compile-tie only as that of a parent class, although it may actually be of a child class which would be bigger). He doesn't know what a VMT is, or know that it contains the size of the object.

Here is what Leon Wagner said:

I don't support this feature and would likely not implement it. Other than the nice discussion of what to name it, I see no compelling reason for its actual use.

> -----Original Message-----
> From: forth200x@yahoogrou ps.com [mailto:forth200x@yahoogrou ps.com] On Behalf Of Hugh Aguilar
> Sent: Friday, January 29, 2010 2:41 PM
> To: forth200x@yahoogrou ps.com
> Subject: [forth200x] SIZE RfD

> My .NODE-SIZE field is a waste of memory. This information is held internally (FREE and RESIZE are able to obtain
> it), so there is no need for me to hold onto it as well.

For hosted systems that use the heap management of the underlying OS, the internal information is "under the hood" and not available to us. This means that each and every call to ALLOCATE would have allocate additional space, retain the size, and fudge the pointers returned by ALLOCATE and used by FREE. Now *that* does seem wasteful.

I do not understand the argument that C++ programmers don't understand the need to keep track of allocated memory. As far as I know, the traditional malloc and free are still in use, as well as new and delete (or new[] and delete[]). But there's no "size of" memory space allocated. Is there?

--Leon


> Why would it be different? If you and Hugh cannot agree on a name
> (and probably not on a common specification, either), that's certainly
> not the fault of the standardization process; on the contrary, it
> would explain why there is no progress in standardizing this feature.

This is totally dishonest. You are saying that the RfD died because myself and Albert couldn't agree on the name? Bullshit! We were having a "nice discussion" about the name, then Leon killed the RfD and the discussion ended. I had agreed that SIZE (my original suggestion) was a bad name. The names proposed were ALLOCATION (for the exact amount of memory requested) and ALLOCATED (for the amount of memory actually provided). That was fine with me. The ALLOCATED value is actually better because this is certainly stored internally, whereas the ALLOCATION value is not necessarily stored internally --- the ALLOCATED value is adequate for copying the object (there might be a few extra bytes copied, but that is not a problem) --- copying nodes without knowing their data type is the whole point of this.

Anyway, Forth-200x is a joke --- it is totally owned by Forth Inc. --- it is "astro turf" in the sense that a lot of effort is made (mostly by you) to present an image of it being a grassroots effort, but it is actually just SwiftForth.

All of the Forth-200x committee members are on Forth Inc.'s payroll, so they just do what their boss Leon Wagner tells them to do --- it is the same as at any corporation.

Alex McDonald

unread,
Jun 7, 2015, 5:51:18 AM6/7/15
to
on 07/06/2015 03:35:16, wrote:
> On Saturday, June 6, 2015 at 9:18:59 AM UTC-7, Anton Ertl wrote:
>> alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
>> >In article <8021c02c-0a0c-42ef...@googlegroups.com>,
>> > <hughag...@gmail.com> wrote:
>> >>I wrote an RfD for Forth-200x asking that we have a word that, given th
> e
>> >>address of a memory-block in the heap, returns its size. This seemed
>> >>super-easy to me, because the information is already stored (FREE and
>> >>RESIZE access this information to do what they do). Everybody seemed to
>> >>like the idea, but then Leon Wagner killed it by saying that he wouldn'
> t
>> >>implement this in SwiftForth and he didn't understand what it was for.
>>
>> The SIZE RfD is still listed among the RfDs without CfVs. I guess we
>> should do some timeout of RfDs after some time, though.
>
> There is no need for an RfD to time-out --- there can be no further
> discuss ion after Leon kills an RfD, because Forth Inc. owns
> Forth-200x. The follow ing is how Leon Wagner killed the RfD. Notice
> how he is unaware of the size of operator in C++, and also unaware
> that objects can be copied when their type is not known at run-time
> (the type was declared at compile-tie only as that of a parent class,
> although it may actually be of a child class which would be bigger).
> He doesn't know what a VMT is, or know that it contains the size of
> the object.
>
> Here is what Leon Wagner said:
>
> I don't support this feature and would likely not implement it. Other
> than the nice discussion of what to name it, I see no compelling
> reason for its actual use.
>
>> -----Original Message-----
>> From: forth200x@yahoogrou ps.com [mailto:forth200x@yahoogrou ps.com] On B
> ehalf Of Hugh Aguilar
>> Sent: Friday, January 29, 2010 2:41 PM
>> To: forth200x@yahoogrou ps.com
>> Subject: [forth200x] SIZE RfD
>
>> My .NODE-SIZE field is a waste of memory. This information is held intern
> ally (FREE and RESIZE are able to obtain
>> it), so there is no need for me to hold onto it as well.
>
> For hosted systems that use the heap management of the underlying OS,
> the i nternal information is "under the hood" and not available to us.
> This means that each and every call to ALLOCATE would have allocate
> additional space, retain the size, and fudge the pointers returned by
> ALLOCATE and used by F REE. Now *that* does seem wasteful.
>
> I do not understand the argument that C++ programmers don't understand
> the need to keep track of allocated memory. As far as I know, the
> traditional m alloc and free are still in use, as well as new and
> delete (or new[] and de lete[]). But there's no "size of" memory space
> allocated. Is there?
>
> --Leon
>
>
>> Why would it be different? If you and Hugh cannot agree on a name
>> (and probably not on a common specification, either), that's certainly
>> not the fault of the standardization process; on the contrary, it
>> would explain why there is no progress in standardizing this feature.
>
> This is totally dishonest. You are saying that the RfD died because
> myself and Albert couldn't agree on the name? Bullshit! We were having
> a "nice dis cussion" about the name, then Leon killed the RfD and the
> discussion ended. I had agreed that SIZE (my original suggestion) was
> a bad name. The names proposed were ALLOCATION (for the exact amount
> of memory requested) and ALL OCATED (for the amount of memory actually
> provided). That was fine with me. The ALLOCATED value is actually
> better because this is certainly stored in ternally, whereas the
> ALLOCATION value is not necessarily stored internally --- the
> ALLOCATED value is adequate for copying the object (there might be a
> few extra bytes copied, but that is not a problem) --- copying nodes
> wit hout knowing their data type is the whole point of this.
>
> Anyway, Forth-200x is a joke --- it is totally owned by Forth Inc. ---
> it i s "astro turf" in the sense that a lot of effort is made (mostly
> by you) to present an image of it being a grassroots effort, but it is
> actually just SwiftForth.
>
> All of the Forth-200x committee members are on Forth Inc.'s payroll,
> so the y just do what their boss Leon Wagner tells them to do --- it
> is the same a s at any corporation.
>

I wasn't a big fan either. You kept banging on about GLIBC for some
reason I couldn't quite fathom. And don't blame Leon; that's the usual
paranoia kneejerk you have any time anyone from Forth Inc disagrees with
you. You simply failed to make your argument. I was then supporting a
Forth compiler (Win32Forth) and I too didn't support this feature and
didn't implement it.


https://groups.google.com/forum/message/raw?msg=comp.lang.forth/9HGIOO6zyag/ga5Qiy45m0wJ

Bernd Paysan

unread,
Jun 8, 2015, 5:24:16 PM6/8/15
to
Anton Ertl wrote:

>>But the above means that it will not be standardised as say a controlled
>>word because those systems would have to admit that they can't implement
>>it. "We implement the total of the Forth language" would no longer be
>>true. So SIZE is kept out of the standard, and although you and I
>>implement the same word, its name would be different.
>
> Why would it be different? If you and Hugh cannot agree on a name
> (and probably not on a common specification, either), that's certainly
> not the fault of the standardization process; on the contrary, it
> would explain why there is no progress in standardizing this feature.

One of the problem of the SIZE proposal is that it's not well specified,
which size. Aparently, Hugh just wants to know how much memory the
allocater actually used, to allow cloning of lists without knowing what kind
of data is inside the list. The other possible reason is to get what was
actually allocated, which can be used to allocate strings and query the
string length. The second usage is not possible if you just return the size
of the actual memory chunk, but it's more useful.

In current GLIBC, it's fairly easy to implement SIZE:

: SIZE ( addr -- len ) 1 cells - @ -2 cells and ;

This hasn't changed since last time I looked at that, and that was when Hugh
proposed his RfD. We could run an automated test which checks if this
works, and if not, do a fallback on a solution which stores another cell.
So I don't agree that it is prohibitive to implement that.

A memory allocater which works like the one of GLIBC could as well store the
actual size, and not the padded one, as doing the padding is a simple
operation, and it's not really harmful to do that on free() as well.

However, I could think of a very different way on allocating small blocks,
especially on a 64 bit machine: I'd use mmap to grab a pretty large chunk of
memory, and then subdivide it into e.g. 256 regions, each of which is
responsible for 1..256*16 bytes objects. All objects greater 4k (one page)
can use a different allocater, with more overhead per object.

Computing the size of the smaller ones is easy, just subtract the start
address of the big mmap area, and then extract the part of the address which
indicates the size. One mmap on 64 bit Linux is limited to ~4GB, so if you
run out of space and need another map, try to map it fixed on an address
related to the previous map (that way, obtaining the size still works).

malloc() would first check the free list for that size, to give you the last
freed block of that size (that's good for cache locality to always re-
allocate the last freed block; it has been touched recently); if the free-
list of that size is empty, return the first-unused pointer for that size,
and increment that pointer. free() just inserts the block into the free
list for that size.

In this scheme, it's not reasonable to store the actual requested size, i.e.
you only get the size with padding. But the allocate/free operation could
be really fast, and you don't waste any memory for storing the size. The
implementation is trivial, size effectivity is very high (only the alignment
padding overhead), and LIFO reuse is cache friendly and makes use-after-free
bugs obvious.

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
net2o ID: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ*
http://bernd-paysan.de/

Anton Ertl

unread,
Jun 9, 2015, 4:07:30 AM6/9/15
to
Bernd Paysan <bernd....@gmx.de> writes:
>Anton Ertl wrote:
>> Why would it be different? If you and Hugh cannot agree on a name
>> (and probably not on a common specification, either), that's certainly
>> not the fault of the standardization process; on the contrary, it
>> would explain why there is no progress in standardizing this feature.
>
>One of the problem of the SIZE proposal is that it's not well specified,
>which size. Aparently, Hugh just wants to know how much memory the
>allocater actually used, to allow cloning of lists without knowing what kind
>of data is inside the list. The other possible reason is to get what was
>actually allocated, which can be used to allocate strings and query the
>string length. The second usage is not possible if you just return the size
>of the actual memory chunk, but it's more useful.

The first usage would be useful for a region allocator.

The rationale for this thing is that the information is present anyway
(for FREE), and this holds only for the first usage.

>A memory allocater which works like the one of GLIBC could as well store the
>actual size, and not the padded one, as doing the padding is a simple
>operation, and it's not really harmful to do that on free() as well.

Ok, but we don't want to restrict the allocator to have this property,
do we? E.g., it would rule out buddy allocators. If we did, we could
just have two words: One for the requested size, and one for the
actual size.

Alex McDonald

unread,
Jun 9, 2015, 7:09:56 AM6/9/15
to
on 08/06/2015 22:24:14, Bernd Paysan wrote:
> Anton Ertl wrote:
>
>>>But the above means that it will not be standardised as say a controlled
>>>word because those systems would have to admit that they can't implement
>>>it. "We implement the total of the Forth language" would no longer be
>>>true. So SIZE is kept out of the standard, and although you and I
>>>implement the same word, its name would be different.
>>
>> Why would it be different? If you and Hugh cannot agree on a name
>> (and probably not on a common specification, either), that's certainly
>> not the fault of the standardization process; on the contrary, it
>> would explain why there is no progress in standardizing this feature.
>
> One of the problem of the SIZE proposal is that it's not well
> specified, which size. Aparently, Hugh just wants to know how much
> memory the allocater actually used, to allow cloning of lists without
> knowing what kind of data is inside the list.

Exactly. It looked like an application aide memoire rather than a useful
feature of the language.

> The other possible
> reason is to get what was actually allocated, which can be used to
> allocate strings and query the string length. The second usage is not
> possible if you just return the size of the actual memory chunk, but
> it's more useful.
>
> In current GLIBC, it's fairly easy to implement SIZE:
>
>: SIZE ( addr -- len ) 1 cells - @ -2 cells and ;
>
> This hasn't changed since last time I looked at that, and that was
> when Hugh proposed his RfD. We could run an automated test which
> checks if this works, and if not, do a fallback on a solution which
> stores another cell. So I don't agree that it is prohibitive to
> implement that.

On Windows that doesn't work (but you probably knew that).
This assumes a set of well ordered and user definable allocators. Windows
supports multiple heaps, uses different allocators for the same heap
dependant on the size of the request, supports reservation vs commit. A
Windows application that reserves but doesn't commit a huge chunk of
memory would be considered badly behaved. It requires backing storage,
builds page tables that are pinned but never referred to, and increases
TLB costs. To commit large areas would cause significant amounts of work,
since pages are zeroed for reasons of security; zeroing say 4GB is a non-
trivial start up cost.

One could argue that Windows could use malloc. That adds a library (the
CRT or C runtime) and a layer of obfuscation over the underlying Windows
allocators. Windows does not have system wide user definable allocators;
at bottom the Windows allocators are used by the CRT.

The language does not need to accomodate any of this beyond ALLOCATE and
FREE. A Forth library that works directly with ALLOCATE and FREE leaves
the implementor complete freedom as to how and what facility to use.
malloc for you, a SLAB allocator for him, HeapAlloc for me.

A suitable Windows implementation is left as an exercise for the reader.
Here's mine.

\ Windows heap function calls
1 import: GetProcessHeap
3 import: HeapAlloc
3 import: HeapFree
4 import: HeapReAlloc

\ The memory allocation code uses HEAP_GENERATE_EXCEPTIONS rather than
returning \ false on the stack. The reason is simple; crashing on a known
exception is \ easier than a crash further down the line on some other
exception. Early & \ informative is best. But if you want ANS behavior,
call ANS-MEMORY

create process-heap \ process heap address
0 , \ heap address
HEAP_GENERATE_EXCEPTIONS , \ flag should be zero to pass ANS test

: ans-memory ( -- ) [ process-heap cell+ ] literal off ;
: heap&flag@ ( -- fl heap ) process-heap 2@ ;
: allocate ( n -- a f ) heap&flag@ call HeapAlloc dup 0= ;
: malloc ( n -- a ) allocate throw_memallocfail ?throw ;
: free ( a -- f ) heap&flag@ call HeapFree 0= ;
: release ( a -- ) free throw_memrelfail ?throw ;
: realloc ( n a -- a' f ) dup>r heap&flag@ call HeapReAlloc
?dup if r>drop 0 else r> -1 then ;
: resize ( a n -- a' f ) swap ?dup if realloc else allocate then ;
: init-malloc ( -- ) call GetProcessHeap process-heap ! ;


Bernd Paysan

unread,
Jun 9, 2015, 5:25:51 PM6/9/15
to
Alex McDonald wrote:
> This assumes a set of well ordered and user definable allocators. Windows
> supports multiple heaps, uses different allocators for the same heap
> dependant on the size of the request, supports reservation vs commit. A
> Windows application that reserves but doesn't commit a huge chunk of
> memory would be considered badly behaved. It requires backing storage,
> builds page tables that are pinned but never referred to, and increases
> TLB costs. To commit large areas would cause significant amounts of work,
> since pages are zeroed for reasons of security; zeroing say 4GB is a non-
> trivial start up cost.

I'm thinking of Linux. There, just mmap anonymous 4GB takes essentially no
resources. All it does is to tell the page fault handler that this range is
to be allocated when used. Including the TLB entries (no need to have TLB
entries for yet unused memory). It takes 14µs on my machine to do so (and I
can do it repeatedly, each time taking 14µs).

humptydumpty

unread,
Jun 10, 2015, 3:16:43 PM6/10/15
to
A new version with less gforth-isms and little more factored:

---
$ cat struct.fs
\ Extendable structure with introspection. Wordlist based.
\ USAGE: see code between [IF] [THEN]
\ -----
\ CONS: not a fastest compiling time
\ PROS: could use information at compile-time to compile for a faster execution
\ GForth 0.7.3, PFE 0.33.71 tested.

\ Uncomment if your forth implementation does not have 'parse-name'
\ CREATE parsebuf 32 allot
\ : parse-name ( 'name' -- ca u )
\ bl word count
\ 32 min >R
\ parsebuf R@ move
\ parsebuf R>
\ ;

\ Cure for redefinition of Forth words
WORDLIST CONSTANT UNTAINTED
get-current UNTAINTED set-current
' + alias +
' VALUE alias VALUE
set-current

: ++order ( wid -- ; )
>R get-order R> UNTAINTED rot 2 + set-order
;
: --order ( -- ; )
get-order nip nip 2 - set-order
;

\ Field compiled by this macro should be used inside scope of a defined structure.
\ See 'struct' definition.
: field ( offs size -- offs+size ; Text based macro )
over >R
: R> ?dup
IF
S>D <# [CHAR] + hold BL hold #S #>
postpone SLITERAL postpone EVALUATE
THEN
postpone ; IMMEDIATE +
;

\ For a safe use of fields defined by text-macro 'field',
\ preserve 'Base' that exists at time of structure definition.
\ Also cures '+','VALUE' redefinitions.
: struct
get-current wordlist ( old-wid wid )
dup CREATE , HERE 0 , ( post-it) IMMEDIATE ( old-wid wid a )
swap dup set-current ++order
0 ( old-wid a 0 ;Now compile fields in struct-wordlist )
DOES>
Base @ >R
dup cell+ @ Base !
@ ++order
parse-name ['] evaluate
CATCH
--order R> Base !
THROW
;
: end-struct ( old-wid a size -- )
S" VALUE SIZE" evaluate
Base @ swap ! ( old-wid ) \ fix-up current 'Base'
set-current --order
;
: extend ( "struct-name" -- old-base old-wid )
Base @ get-current
' >BODY dup
@ dup set-current ++order
cell+ @ Base !
;
: end-extension ( old-base old-wid -- )
set-current --order
Base !
;

: fields-of ( "struct-name" -- ; structure introspection word)
' >BODY @ >R get-order R> swap 1+ set-order words previous
;

0 [IF]

defined ]L 0= [if] : ]L ] postpone LITERAL ; immediate [then] \ PFE

cr ." Test for funny redefinition of 'VALUE': " : VALUE ." WHAT A FUNNY VALUE!" ;
3 Base ! \ Test for independence of 'Base'
struct POS
1 cells field X
1 cells field Y
end-struct
DECIMAL

cr ." Test for funny '+' redefinition: " : + ." funny " + ;

cr ." Test for inspection:"
cr ." POS constituents: " fields-of POS

cr ." Test for scoping of defined structure at interpret/compile-time and fields compiling:"
VARIABLE X 1 X !
CREATE Ob POS SIZE allot
99 Ob POS X !
101 Ob POS Y !

: testX Ob POS X ? X ? ;
: testY [ Ob POS Y ]L ? X ? ;
: 2testY Ob POS Y ? X ? ;
see testX see testY see 2testY
cr testX cr testY cr 2testY

cr ." Test for extending structure:"
extend POS
SIZE
1 cells field Z
TO SIZE
end-extension

' POS alias 3dPOS immediate

cr ." 3dPOS constituents:" fields-of 3dPOS

Create Ob2 3dPOS SIZE allot
2013 Ob2 3dPOS X !
2014 Ob2 3dPOS Y !
2015 Ob2 3dPOS Z !

: testZ Ob2 dup 3dPOS X ? dup 3dPOS Y ? 3dPOS Z ? ;

see testZ
cr testZ

cr .s cr bye
[THEN]
---

Have all a nice day,
humptydumpty
0 new messages