New class(es)

59 views
Skip to first unread message

Wally

unread,
Jul 17, 2009, 11:56:25 PM7/17/09
to OpenQM-OpenSource
Greetings!

As everyone may know, I'm working to port an entire application
package from a COBOL-like language to OpenQM. The old system made
EXTENSIVE use of the dictionary (schema) to make development simple.
This was simply inadequate in OpenQM (and other Pick-like systems).
Then I stumbled upon "DICT.TOOLS.CLS" which seemed intriguing because
it allows direct access to data fields via the dictionary entries.
Well, I've been playing with this A LOT lately and think this may be
what I was looking for. I am extending and enhancing the class
significantly, so to maintain backward compatibility, I have decided
to create a new class "FILE.CLS" based on "DICT.TOOLS.CLS" that has
all of the functionality of DICT.TOOLS.CLS and then some. I also
fixed some bugs in "DICT.TOOLS.CLS". Here is what I've done so far
(if you're not familiar w/ DICT.TOOLS.CLS, please look at it before
continuing):

1) Added the ability to update field values using the following
syntax:

To update a field "customer.name" in a file pointed to by "myobj"
to "ACME INDUSTRIES"
myobj->customer.name = "ACME INDUSTRIES"

2) Added a function set.file.name (rather than a set paragraph) to
allow setting and testing a
return code. So that, to access a file "ORDERS" and test the
result of the open

myobj=OBJECT("FILE.CLS")
IF myobj->set.file.name("ORDERS") ELSE STOP

The set.file.name function now returns true if the open succeeds
and false if it fails. It will
also fail if the dictionary cannot be found/open. I overloaded
the set.file.name method so
that the old usage continues to work (i.e., set.file.name may or
may not return a result)

3) Fixed the logic for I-type fields in the dictionary so that they
are automatically derived
when used (at run time)

4) Changed the logic for fields with a format specification by
calling the FMT function rather
than appending the format to the field value. The previous
method returned values that
would not work in all situations. Be aware that formatted
numeric fields may be returned
as strings (as a result of the formatting). This can be handled
by either:
a) defining a second field without formatting
or b) forcing typing by performing an operation (e.g., myobj-
>num.field+0)

5) Added a "write" method to write the existing data back to the
database. I still need to
add error checking to this method, but it does work as is (just be
careful).

I intend to continue to extend and enhance this class significantly.
Here are some of the
things I am planning (feedback appreciated):

1) Easy access to records via alternate keys (START, READNEXT,
READPREV, etc)

2) Ability to override dictionary entries at run time (WITHOUT
updating dictionary) to allow
altering format or derived-field logic in a single program

3) Full locking reads, writes, and corresponding releases

What I've done already is going to greatly simplify my port. Perhaps
others will find the class useful...

This post is long enough. I'll post some sample code tomorrow.

Thanks for listening,

Gary Walborn

P.S. I'm quite impressed with what I've been able to do using the
object-oriented features of OpenQM. There is more power there than I
realized when I read the documentation.

Glen B

unread,
Jul 18, 2009, 12:36:38 AM7/18/09
to openqm-o...@googlegroups.com
Wally wrote:
> Greetings!
>
> As everyone may know, I'm working to port an entire application
> package from a COBOL-like language to OpenQM. The old system made
> EXTENSIVE use of the dictionary (schema) to make development simple.
> This was simply inadequate in OpenQM (and other Pick-like systems).
> Then I stumbled upon "DICT.TOOLS.CLS" which seemed intriguing because
> it allows direct access to data fields via the dictionary entries.
> Well, I've been playing with this A LOT lately and think this may be
> what I was looking for. I am extending and enhancing the class
> significantly, so to maintain backward compatibility, I have decided
> to create a new class "FILE.CLS" based on "DICT.TOOLS.CLS" that has
> all of the functionality of DICT.TOOLS.CLS and then some. I also
> fixed some bugs in "DICT.TOOLS.CLS". Here is what I've done so far
> (if you're not familiar w/ DICT.TOOLS.CLS, please look at it before
> continuing):
>
>
\o/ I'm glad someone made real use of the class and I'm also happy that
it's being tweaked and extended. I just don't have the spare time to do
it. There is great potential there for simple parametrically driven OOP
design using dicts and some I-type code to glue bits together.

> 1) Added the ability to update field values using the following
> syntax:
>
> To update a field "customer.name" in a file pointed to by "myobj"
> to "ACME INDUSTRIES"
> myobj->customer.name = "ACME INDUSTRIES"
>
>

This was on the TODO list. Thanks for putting the code in to make it work.

> 2) Added a function set.file.name (rather than a set paragraph) to
> allow setting and testing a
> return code. So that, to access a file "ORDERS" and test the
> result of the open
>
> myobj=OBJECT("FILE.CLS")
> IF myobj->set.file.name("ORDERS") ELSE STOP
>
> The set.file.name function now returns true if the open succeeds
> and false if it fails. It will
> also fail if the dictionary cannot be found/open. I overloaded
> the set.file.name method so
> that the old usage continues to work (i.e., set.file.name may or
> may not return a result)
>
>

I never considered return codes. Great catch!

> 3) Fixed the logic for I-type fields in the dictionary so that they
> are automatically derived
> when used (at run time)
>
>

I'm still new to the I-type stuff, so what's there was hacked together
for theoretical testing mostly. Again, thanks for making it work properly.

> 4) Changed the logic for fields with a format specification by
> calling the FMT function rather
> than appending the format to the field value. The previous
> method returned values that
> would not work in all situations. Be aware that formatted
> numeric fields may be returned
> as strings (as a result of the formatting). This can be handled
> by either:
> a) defining a second field without formatting
> or b) forcing typing by performing an operation (e.g., myobj-
>
>> num.field+0)
>>
>
>

Would it be useful to have a method to inquire on the assumed data
type? I.E. myobj->set.field.name("some.field.name"); this.field.type =
myobj->get.data.type. The return code could be compared with an integer
or a system variable like DTYPE$NUMERIC, DTYPE$DATE, DTYPE$STRING, etc.

> 5) Added a "write" method to write the existing data back to the
> database. I still need to
> add error checking to this method, but it does work as is (just be
> careful).
>
>
The error checking the toughest part!

> I intend to continue to extend and enhance this class significantly.
> Here are some of the
> things I am planning (feedback appreciated):
>
> 1) Easy access to records via alternate keys (START, READNEXT,
> READPREV, etc)
>
>

How do you plan on making that work from the object instance?

> 2) Ability to override dictionary entries at run time (WITHOUT
> updating dictionary) to allow
> altering format or derived-field logic in a single program
>
>

The data type inquiry I mentioned could be duplicated or modified to be
a multiple-purpose input/ouput method to change the behavior of the data
read and write. I don't approve of changing the data type in the write
since it can lead to data corruption, but let the people play as they will.

> 3) Full locking reads, writes, and corresponding releases
>
>

That's a definite must, but once again I just don't have the time. Let
me know when you get a working demo in the dev branch. I wish someone
could post some sample data to play with too.

> What I've done already is going to greatly simplify my port. Perhaps
> others will find the class useful...
>
> This post is long enough. I'll post some sample code tomorrow.
>
> Thanks for listening,
>
> Gary Walborn
>
> P.S. I'm quite impressed with what I've been able to do using the
> object-oriented features of OpenQM. There is more power there than I
> realized when I read the documentation.
>
>
QMOO is nice eh? I wish more people took advantage of it. The method
overloading and inheritance makes quick work of some typically complex
BASIC subroutine designs.
> >
>
>


GlenB

Steve Bush

unread,
Jul 18, 2009, 3:46:42 AM7/18/09
to openqm-o...@googlegroups.com
Very impressive Gary! ... and Glenn for kicking it off.

Glen B

unread,
Jul 19, 2009, 1:35:56 AM7/19/09
to openqm-o...@googlegroups.com
Wally wrote:

> what I was looking for. I am extending and enhancing the class
> significantly, so to maintain backward compatibility, I have decided
> to create a new class "FILE.CLS" based on "DICT.TOOLS.CLS" that has
> all of the functionality of DICT.TOOLS.CLS and then some. I also
> fixed some bugs in "DICT.TOOLS.CLS". Here is what I've done so far
> (if you're not familiar w/ DICT.TOOLS.CLS, please look at it before
> continuing):
>

Gary,

I just reread your first paragraph and totally missed a tidbit. I
wouldn't worry too much about backwards compat at this point. It's a
work-in-progress and the Wiki states that under the "wishlist" page. The
only way you can deploy the class is to grab the code from the dev
branch using SVN. If you don't maintain the properties or methods that
are there, then just document it on the list so that everyone knows
what's going to change at commit time.

I would post a poll on class name before digging too deeply into
application test code. FILE.CLS is a bit general for my taste.
DICT.TOOLS.CLS is specific
enough to not step on toes later but it's general enough to encompass
everything dictionary<=>data related. It can be inherited into parent
classes and extended without fear of class name collision or confusion.
I'm not sure if you're planning on doing that or if you are going to
replace the entire class.

If you are going to create something called FILE.CLS then normal
file I/O methods and properties should be applicable. I.E. include
attribute-oriented read/write/readseq/etc methods and plug the
DICT.TOOLS.CLS stuff in along side it. This would be a great time to
toss in automatic operations like making data diffs available between
read/write calls and laying out an I/O user plug-in structure so that
SQL and other external databases can be replicated/compared with one
local data write/read. If a developer doesn't want all of that fluff to
happen, then the plain-vanilla I/O functions are always available in
QMOO and QMBASIC.

Regards,

GlenB

Gary

unread,
Jul 19, 2009, 10:01:55 AM7/19/09
to OpenQM-OpenSource
Glen,

I think I am working more along the lines of the second
approach. I chose "FILE.CLS" because what I am going to end up with
is actually closer to the way "FILE" works in QMBasic. It was quite
by chance that I discovered the real purpose of DICT.TOOLS.CLS (by
reading a post). I had assumed from the name that DICT.TOOLS.CLS was
more for managing/manipulating dictionaries than doing dictionary-
based file access. I have replaced the "set.item.id" method by two
methods, "read" and "readl" and "set.file.name" by "open". I have
added "write", "writeu", and "release" methods. So you can see that
this is getting much closer to a "file" type object than a "tool" type
object. Perhaps something like "DICTFILE.CLS"? I'm open to
suggestions.

Here is some sample code using the class and the output:
PROGRAM TESTMYC
ADJUST=OBJECT("FILE.CLS")
IF ADJUST->OPEN("ADJUST") THEN PRINT "WORKED" ELSE PRINT
"FAILED";STOP
OPEN "ADJUST" TO ADJUST.F ELSE PRINT "OPEN FAILED"; STOP
SELECT ADJUST.F ON ERROR PRINT "SELECT FAILED"; STOP

LOOP:
READNEXT ADJUST.ID ELSE GO TO DONE
IF ADJUST->READL(ADJUST.ID) ELSE PRINT "READL FAILED"
ADJUST->CO.NO = 4
PRINT ADJUST->KEY, ADJUST->CO.NO, ADJUST->AMOUNT.SIGNED
IF ADJUST->WRITE() ELSE PRINT "WRITE FAILED"
GO TO LOOP
DONE:
END

and the output:

04D0000004695BFD000 04 -116.08
04D0000004647BFD000 04 -100.00
04D0000004771BFD000 04 -173.00
04D0000001257BFD000 04 -158.79
04D0000004593BFD000 04 -71.00
04D0000004789BFD000 04 -339.01
04D0000004696BFD000 04 -210.32
04D0000004708BFD000 04 -150.00
04D0000004701BFD000 04 -200.00
04D0000001086BFD000 04 -526.22

Some things to note...
ADJUST->KEY and ADJUST->AMOUNT.SIGNED are both I-type (derived)
fields. They are automatically derived when needed and formatted via
the appropriate dictionary entries. ADJUST->CO.NO is a D-type entry
and is read and formatted at run time via the dictionary definition.
AMOUNT.SIGNED is defined as follows:

Id: AMOUNT.SIGNED
1: TYPE/DESC=I
2: LOC =IF (TYPE = 'D') OR (TYPE = 'X') THEN AMOUNT * -1 ELSE
AMOUNT
3: CONV =4
4: NAME =Adjust Amount
5: FORMAT =12' 'R2
6: S/M =S
7: ASSOC =

and KEY is:

]Id: KEY
1: TYPE/DESC=I
2: LOC =FMT(CO.NO,"R%2"):FMT(PR.TYPE,"1L"):FMT
(TRAILER.NO,"10L"):FMT(CODE,"3L"):FMT(SEQ.NO,"R%3")
3: CONV =
4: NAME =
5: FORMAT =19' 'L
6: S/M =S
7: ASSOC =

I think this is coming along quite nicely and I'd appreciate
everyone's input, suggestions, and criticisms.

Gary



Glen B

unread,
Jul 19, 2009, 1:04:05 PM7/19/09
to openqm-o...@googlegroups.com
Gary wrote:
> Glen,
>
> I think I am working more along the lines of the second
> approach. I chose "FILE.CLS" because what I am going to end up with
> is actually closer to the way "FILE" works in QMBasic. It was quite
> by chance that I discovered the real purpose of DICT.TOOLS.CLS (by
> reading a post). I had assumed from the name that DICT.TOOLS.CLS was
> more for managing/manipulating dictionaries than doing dictionary-
> based file access. I have replaced the "set.item.id" method by two
> methods, "read" and "readl" and "set.file.name" by "open". I have
> added "write", "writeu", and "release" methods. So you can see that
> this is getting much closer to a "file" type object than a "tool" type
> object. Perhaps something like "DICTFILE.CLS"? I'm open to
> suggestions.
>
> Here is some sample code using the class and the output:
> PROGRAM TESTMYC
> ADJUST=OBJECT("FILE.CLS")
> IF ADJUST->OPEN("ADJUST") THEN PRINT "WORKED" ELSE PRINT
> "FAILED";STOP
> OPEN "ADJUST" TO ADJUST.F ELSE PRINT "OPEN FAILED"; STOP
> SELECT ADJUST.F ON ERROR PRINT "SELECT FAILED"; STOP
>
> LOOP:
> READNEXT ADJUST.ID ELSE GO TO DONE
>

The list select and readnext can be wrapped in methods if you want
cleaner code. The file handle is in memory for the instance of the
object and if you are not doing sort-selecting then after the file is
opened it could be selected by default in the "open" method. An
alternate method for sort-selection can be added so that you can pass
sorting parameters through the open call. The only issue with putting
the select in "open" is, from what I understand, that if you instantiate
multiple file objects within the same code base only the last
instantiation will contain the file in list zero(default). If you
instantiate file1 and then file2, file2's item-ID list will be
active(list zero) and code will break if the readnext loop solely
assumes file1 based on the object pointer name being used. Martin, if
this is wrong please say so.

There are two ways to deal with that, if what I stated was correct:

1) In "open", select the file to a specific list name. The readnext
method will refer to it based on the internal filename variable at
run-time. There should be no confusion as object pointers change the
scope of the I/O at run-time.

2) Implement a select list assignment method, which will be very
expensive if the scope of the I/O flip-flops a lot between files in the
main program.


#1 is doable, but even if we have to do #2 there is still the issue of
the list pointer being reset. When you issue a list selection, I'm
fairly certain that the pointer is reset to the top. So, not only will
the lists have to be managed by filename in globals, but the last
readnext call must be cached in private memory so that subsequent
readnext calls will pick up from the last item-ID within scope of the
file object instance. Consider top-down code with multiple SELECT
statements flipping between several files. It'd be a pain to code in
QMBASIC, but I think it can be done efficiently in QMOO.

If any of this is unclear please ask questions.

Are I-types being used to update data as well? Looks like you've done
a bit of expanding. I think this will be a viable feature to advertise
once it's gone through testing and release approval. I doubt there will
be any friction for release approval. Getting test cases done may be a
bit more challenging, considering there aren't a lot of QMOO users.
Maybe this class, and lots of how-to documentation, will help stimulate
QMOO usage in existing apps.

Regards,

GlenB

Gary

unread,
Jul 19, 2009, 2:34:59 PM7/19/09
to OpenQM-OpenSource
Glen,

First, thanks for all your help! Secondly, I haven't quite
decided just how much to include in the class. I made a few more
changes.

1) Added "close" method to close open files
2) Added "readu" method to perform readu on data
3) Added get method "file" that returns the file pointer

I was hesitant to do the later, but it make many things much easier
(at the programmer's peril, of course). That makes the first few
lines of my program read:

IF ADJUST->OPEN("ADJUST") THEN PRINT "WORKED" ELSE PRINT
"FAILED";STOP
SELECT ADJUST->FILE ON ERROR PRINT "SELECT FAILED"; STOP
LOOP:
READNEXT ADJUST.ID ELSE GO TO DONE

eliminating the need for a second file variable to get the index.
This actually makes for pretty concise, clean code (I think).
Actually, I might eliminate the "close" method and put that logic in
the object destructor.

I'm not exactly sure if I understand your last question... You CANNOT
make an assignment to an I-type variable. They are essentially 'read
only'. The ability to resolve these item types are run time was
ESSENTIAL to my port, because SystemZ makes extensive use of derived
fields. It solved my "KEY" problem to ease compatibility with the
ISAM database where my data is now. I make the KEY an I-type field so
that the KEY value can be used for the record ID and is calculated at
run time.

Gary

Glen B

unread,
Jul 19, 2009, 5:17:09 PM7/19/09
to openqm-o...@googlegroups.com
Gary wrote:
> Glen,
>
> First, thanks for all your help! Secondly, I haven't quite
> decided just how much to include in the class. I made a few more
> changes.
>
>

I'm happy to help, especially when progress is being made to such a
useful project!

> 1) Added "close" method to close open files
> 2) Added "readu" method to perform readu on data
> 3) Added get method "file" that returns the file pointer
>
> I was hesitant to do the later, but it make many things much easier
> (at the programmer's peril, of course). That makes the first few
> lines of my program read:
>
> IF ADJUST->OPEN("ADJUST") THEN PRINT "WORKED" ELSE PRINT
> "FAILED";STOP
> SELECT ADJUST->FILE ON ERROR PRINT "SELECT FAILED"; STOP
> LOOP:
> READNEXT ADJUST.ID ELSE GO TO DONE
>
> eliminating the need for a second file variable to get the index.
> This actually makes for pretty concise, clean code (I think).
> Actually, I might eliminate the "close" method and put that logic in
> the object destructor.
>
>

Make sure that the "file" method returns null if there is no open
file. I'm sure you've already implemented that, but it drastically
affects the following statements.

Yes, put it in the destructor call. I would agree that a close method
should also be provided for instances where file objects have a short
life and numerous files are being opened and closed in a sequential
order. It is more efficient to reuse the same object instance and clear
the private variables(as is done automatically for the data and
dictionaries) than to create and destroy a bunch of objects for one or
two data hits per file. I would also check, in the "open" method, if the
private file handle is assigned. If it is, the current file should be
closed if the requested file name and the existing file name do not
match. Otherwise, there will be lingering file handles with no variable
assignments to use. They will all be closed when the application
completes, but not dealing with it from all angles could lead to some
performance issues with phantoms and other continuously running code
that gets ignored. IIRC file handles are cached and subsequent opens for
specific files will not be duplicated in memory. As far as multiple
pointer/handle assignments for the same file, I vaguely remember Martin
saying that they're all just memory pointers to the same place. How that
affects a piece of code running 24/7, I'm not sure. The question to
Ladybridge is; if the same file is opened 5,000 times to different
variables, will it impact memory usage? Of course, it won't matter if we
don't put our code in that position. :)


> I'm not exactly sure if I understand your last question... You CANNOT
> make an assignment to an I-type variable. They are essentially 'read
> only'. The ability to resolve these item types are run time was
> ESSENTIAL to my port, because SystemZ makes extensive use of derived
> fields. It solved my "KEY" problem to ease compatibility with the
> ISAM database where my data is now. I make the KEY an I-type field so
> that the KEY value can be used for the record ID and is calculated at
> run time.
>
> Gary
>

It would be possible to use the I-type defs to update data. It has
been mentioned before on the list that this was warranted in some cases,
but I'm still not convinced. My vote is to leave I-type updates out for
the time being. If someone wants to extend their own local copy of the
class then it's fair game on their own server. I will concede that
I-types are 'blind faith' as it is, for reading data and that writing
via the same method is no different.

[chopped due to length]

Regards,

GlenB

Ashley Chapman

unread,
Jul 20, 2009, 5:16:41 AM7/20/09
to openqm-o...@googlegroups.com
Hi Gary,

Nice work with this class.  Good to see you've opted to make it a comprehensive implementation.


the QM run-machine manages file handles, and simply provides a pointer to a table that in implemented internally.  In effect, a WRITE statement will actually resolve to a open-write-close sequence at the operating system level.  This is what allows you to believe you have thousands of files open, even if the OS normally only allows a small number.

With this in mind, I think it would be fine to close a file whenever you think it might not be in use.  I don't think it will cause any bottleneck, and it will reduce the possibility of old handles being re-used erroneously with their old contents.

 


  It would be possible to use the I-type defs to update data. It has
been mentioned before on the list that this was warranted in some cases,
but I'm still not convinced. My vote is to leave I-type updates out for
the time being. If someone wants to extend their own local copy of the
class then it's fair game on their own server. I will concede that
I-types are 'blind faith' as it is, for reading data and that writing
via the same method is no different.

Nope, I don't understand this idea either, as you can't write to an I-type in a record.  I guess you might be referring to the in-memory copy of the record.  That would be possible. In essence, you would allow for I-types to be recalculated, before the record/object is updated.  That might be possible, but I would think it quite dangerous if the record has not been written to disk.  Results might depend upon the exact coding of the I-type, which could make for obscure debugging.  AREV/OI allowed this in an entry form, and it was very useful, but you had to be aware of what was happening when you created the symbolic fields (I-type).


Are you also allowing C-type support?  It would be great if you are, as C-types are just like I-types, but allow for much more of the BASIC syntax to be used.  In a nutshell, I-types are restricted to a single expression whereas C-types can be entire programmes.

--
Ashley Chapman

Gary

unread,
Jul 20, 2009, 11:46:16 AM7/20/09
to OpenQM-OpenSource
On Jul 19, 5:17 pm, Glen B <batch...@bellsouth.net> wrote:
>   Make sure that the "file" method returns null if there is no open
> file. I'm sure you've already implemented that, but it drastically
> affects the following statements.

Glen,

Right now I am initializing the file.f variable to a null string (is
that what you meant?).

>   Yes, put it in the destructor call. I would agree that a close method
> should also be provided for instances where file objects have a short
> life and numerous files are being opened and closed in a sequential
> order. It is more efficient to reuse the same object instance and clear
> the private variables(as is done automatically for the data and
> dictionaries) than to create and destroy a bunch of objects for one or
> two data hits per file. I would also check, in the "open" method, if the
> private file handle is assigned. If it is, the current file should be
> closed if the requested file name and the existing file name do not
> match.

OK, I'm closing the file in the destructor now

>    It would be possible to use the I-type defs to update data. It has
> been mentioned before on the list that this was warranted in some cases,
> but I'm still not convinced. My vote is to leave I-type updates out for
> the time being. If someone wants to extend their own local copy of the
> class then it's fair game on their own server. I will concede that
> I-types are 'blind faith' as it is, for reading data and that writing
> via the same method is no different.

I don't really see the need for writing to I-type data items. Note
that if you change a field that CONTRIBUTES to an I-type calculation,
the I-type item will change as the contributing fields are changed
(which is the desirable behavior).

I changed "open" so that if you call "open" when a file is ALREADY
open, it returns an error. I think this is better because it will
catch inadvertent re-use of the instance.

Here are the latest changes to the class (which I renamed
"DICTFILE.CLS"):

* 20 Jul 09 gdw - Added destructor function with close for file.f
* 19 Jul 09 gdw - Added get method for "record" that returns the
current record (item.data)
* 19 Jul 09 gdw - Check for file already opened in "open" (suggested
by gcb)
* 19 Jul 09 gdw - Added "rewrite" method to emulate REWITE verb in
COBOL

Gary

Gary

unread,
Jul 20, 2009, 11:57:04 AM7/20/09
to OpenQM-OpenSource
On Jul 20, 5:16 am, Ashley Chapman <ash.chap...@gmail.com> wrote:
> Hi Gary,
>
> Nice work with this class.  Good to see you've opted to make it a
> comprehensive implementation.
>
Ashley,

Thanks!

> Nope, I don't understand this idea either, as you can't write to an I-type
> in a record.  I guess you might be referring to the in-memory copy of the
> record.  That would be possible. In essence, you would allow for I-types to
> be recalculated, before the record/object is updated.

Actually, the I-type values are re-calculated whenever they are used,
so if the basis for the calculation changes, the I-type changes. This
is the behavior that I desired (it tracks the semantics of derived
variables in SystemZ). It shouldn't be a problem in most instances
and if you want to be absolutely safe, you can rewrite the record
immediately after an operation that would change the value of the I-
type before doing anything else.

> Are you also allowing C-type support?  It would be great if you are, as
> C-types are just like I-types, but allow for much more of the BASIC syntax
> to be used.  In a nutshell, I-types are restricted to a single expression
> whereas C-types can be entire programmes.

I added "support" for C-type items. I use the QMBasic ITYPE verb to
calculate the value and ITYPE is supposed to work for C-type items. I
haven't tested this yet, but I don't see any reason it shouldn't work.

Gary

Glen B

unread,
Jul 21, 2009, 2:36:46 AM7/21/09
to openqm-o...@googlegroups.com
Gary wrote:
> On Jul 19, 5:17 pm, Glen B <batch...@bellsouth.net> wrote:
>
>> Make sure that the "file" method returns null if there is no open
>> file. I'm sure you've already implemented that, but it drastically
>> affects the following statements.
>>
>
> Glen,
>
> Right now I am initializing the file.f variable to a null string (is
> that what you meant?).
>
>

That should do the trick. I can't think of any other situation where
it wouldn't be null and not be assigned to a file handle.

> I don't really see the need for writing to I-type data items. Note
> that if you change a field that CONTRIBUTES to an I-type calculation,
> the I-type item will change as the contributing fields are changed
> (which is the desirable behavior).
>
>

Hmm. I didn't know that, which is why I didn't do much with the I-type
code. :) I'm still a D3 guy, but I'm slowly picking up things in QM.

> I changed "open" so that if you call "open" when a file is ALREADY
> open, it returns an error. I think this is better because it will
> catch inadvertent re-use of the instance.
>
>

Well, if the file names are identical then there is no error.
Automatic closing on non-null file name change is a feature that could
be useful or it could be considered a bug. Are there other opinions?

> Here are the latest changes to the class (which I renamed
> "DICTFILE.CLS"):
>
> * 20 Jul 09 gdw - Added destructor function with close for file.f
> * 19 Jul 09 gdw - Added get method for "record" that returns the
> current record (item.data)
> * 19 Jul 09 gdw - Check for file already opened in "open" (suggested
> by gcb)
> * 19 Jul 09 gdw - Added "rewrite" method to emulate REWITE verb in
> COBOL
>
> Gary
>
>

I'll grab a copy of the dev code one night this week. It's already
way past my bed time. Got a lot going on this week but I hope to have
time thurs night to review it. So far it sounds like you have a good
grasp of QMBASIC and QMOO. Great job!

GlenB

Gary

unread,
Jul 22, 2009, 1:42:06 PM7/22/09
to OpenQM-OpenSource
Glen,

This code is NOT in the dev code. I implemented this in "user
space". I'll upload the source to the Files section.

Gary

Gary

unread,
Jul 24, 2009, 3:54:01 AM7/24/09
to OpenQM-OpenSource
Ashley,

Thought you'd like to know... I had a chance to use a "C-TYPE" item
and it works with DICTFILE.CLS. If you edit the item with SED, make
sure you force the system to re-compile the dictionary entry before
you try to use it.

Gary

Ashley Chapman

unread,
Jul 24, 2009, 4:16:26 AM7/24/09
to openqm-o...@googlegroups.com


2009/7/24 Gary <gwal...@gmail.com>


Ashley,

  Thought you'd like to know... I had a chance to use a "C-TYPE" item
and it works with DICTFILE.CLS.  If you edit the item with SED, make
sure you force the system to re-compile the dictionary entry before
you try to use it.

Excellent!  My editor within Anji forces a recompile automatically so no worries there.

Do you have any time-scale for the release of your modifications?

 

Ashley Chapman

Gary

unread,
Jul 24, 2009, 8:57:30 AM7/24/09
to OpenQM-OpenSource
Ashley,

I've already released a version of DICTFILE.CLS. It's in the FILES
section on the group. It's operational, but I'm going to be posting a
new version of it soon. Grab it and shake it down for me!

Gary

Gary

unread,
Jul 25, 2009, 8:00:55 AM7/25/09
to OpenQM-OpenSource
To all:

I have uploaded a new version of DICTFILE.CLS. Here are the
changes:

1) Fixed MAJOR bug in READ, READU, READL

2) Added a private member 'object.id' which is a random 8-digit number
assigned when the object is created. This is a first attempt to allow
an equality test to see if two variable point to the same instance of
an object (e.g., IF A->OBJID = B->OBJID THEN...). I would like to
find a way to generate a UNIQUE ID every time I create a DICTFILE.CLS
object. If anyone has any suggestions, please send them along. I
added this because I found that direct comparison of object instances
causes a runtime error. This probably should be fixed in the system
by the addition/testing of an object ID in all objects.

3) It became apparent that it is sometimes helpful (if not necessary)
to get data that has not been formatted according to the format entry
in the dictionary. After some deliberation about how to do this, I
added a flag in the class that is initially set to 'normal' or
formatted mode. To set a DICTFILE to unformatted mode, invoke method
"MYOBJ->SET.FORMAT.RAW" and to change output back to formatted call
"MYOBJ->SET.FORMAT.NORMAL". This may be done at any time and only
affects subsequent reads. Also added "FORMAT.MODE" which returns the
current mode "RAW" or "NORMAL".

4) Added access method for "dictrec" so that you can directly get the
dictionary entry for the last data item accessed without forcing
another read of the DICT file.

Finally, when adding all these members and methods, I have to wonder
about increased chance of name collision with fields in files.
Obviously, the last change precludes access to a field named
"FORMAT.MODE". This is worrisome. Would you like to see a common
prefix to all such items to make them more unique? Any suggestions?

Thanks,
GaryW

Steve Bush

unread,
Jul 25, 2009, 8:35:26 AM7/25/09
to openqm-o...@googlegroups.com
Hi Gary, would it be easy and useful to post the class declaration here to
maximise everybody's comprehension of the interface? Or is a qmoo
implementation all merged with the declaration and not so easy and useful.
Steve

> -----Original Message-----
> From: openqm-o...@googlegroups.com [mailto:openqm-

> opens...@googlegroups.com] On Behalf Of Gary
> Sent: 25 July 2009 16:01
> To: OpenQM-OpenSource
> Subject: [OSS] Re: New class(es)
>
>
> To all:
>
> I have uploaded a new version of DICTFILE.CLS. Here are the
> changes:

<snipe>

Gary

unread,
Jul 25, 2009, 2:34:34 PM7/25/09
to OpenQM-OpenSource
Steve,

The class is pretty well documented in comments at the beginning
of the class. It's still evolving, but is useful as-is. You can grab
the class from the "Files" section of the group and start using it.

GaryW

Gary

unread,
Aug 1, 2009, 8:48:30 AM8/1/09
to OpenQM-OpenSource
To all:

Just uploaded a new version of DICTFILE.CLS with the following
enhancements:

* 30 Jul 09 gdw - Added filename as optional argument to
constructor, eliminating need for separate open
* 30 Jul 09 gdw - Added optional argument to dictrec to retrieve the
dictionary entry for given field
* 25 Jul 09 gdw - Fixed read, readu, readl logic to correspond to
standard QBasic handling
* 24 Jul 09 gdw - Added object.id and access method 'objid' to
create random id for testing (needs work, s/b unique)

Have fun!

GaryW

GlenB

unread,
Aug 12, 2009, 12:58:33 AM8/12/09
to OpenQM-OpenSource
Gary,

Everything looks good from what I've scanned over. I will have to
devote a couple of hours to testing with the little bit of sample data
I have. I think that this class could use a wiki section with property
and method syntax and examples. It would also be useful to have sample
QMOO code. I may use this as a QMOO example for a Spectrum article if
I can find time to write it. Now, how silly would it be to plug this
class back into the compiler to create dictionary-oriented read/write/
query statements? Some people just won't get the power of QMOO, so it
would be neat to have a core class that offers similar functionality
in QMBASIC and QMOO.

GlenB

Joseph von Arx

unread,
Dec 5, 2016, 9:40:33 PM12/5/16
to OpenQM-OpenSource
Gary,

I realize that this thread is several years old, but I was interested in viewing the latest DICTFILE.CLS.  Where is the user space that you refer to?  I'm new to OpenQM and was initially intrigued with the QMOO capabilities and potential.  I hope interest hasn't dwindled away.

Joseph
Reply all
Reply to author
Forward
0 new messages