rochus-keller / Oberon

Oberon parser, code model & browser, compiler and IDE with debugger, and an implementation of the Oberon+ programming language
GNU General Public License v2.0
463 stars 30 forks source link

Issues with Sqlite binding code #24

Closed tenko closed 2 years ago

tenko commented 2 years ago

Code in Gist

I introduced a procedure strcpy(src: *[]char): PString in Sqlite.obx with a loop to copy the string content as a assignment gives an error:

error: right side CPOINTER TO CARRAY OF CHAR of assignment is not compatible with left side POINTER TO ARRAY OF CHAR

This can be improved or simplified?

Also there was an issue with accessing the returned error in Test.obx :

  pcall(res, testdb, db)
  case res of
  | Sqlite.TError: printerr(res) raise()
  end

With the error:

error: actual parameter type RECORD not compatible with formal type POINTER TO RECORD

However the code below works and seems to access the pointer?

  pcall(res, testdb, db)
  case res of
  | Sqlite.TError: println(res.str()^) println(db.errmsg()^) raise()
  end
rochus-keller commented 2 years ago

assignment gives an error ... This can be improved or simplified?

The pointers cannot be assigned, but you can assign the arrays. Do it this way: ret^ := src^.

However the code below works and seems to access the pointer?

Looks like an error in the type case statement.

It works if I redeclare the signature of printerr to proc printerr(in err: Sqlite.TError).

It also works if I redeclare the case label to | Sqlite.Error:. I have to scrutinize the spec wether it is reasonable that this version works and the other doesn't.

tenko commented 2 years ago

Thanks. Pointer to pointer. Should be obvious. The case issue not to important. It just created a bit head scratching. Otherwise the code looks remarkable clean and simple to read. The new exception handling is very nice addition.

rochus-keller commented 2 years ago

The case issue is actually interesting and yet undecidable from the specification. I thus prepare to do experiments with different Oberon compilers to empirically find out how the language is supposed to work. My current compiler is implemented "by the letter" of the specification parts I inherited from previous Oberon versions. E.g. the "The Programming Language Oberon, Revision 1.10.2013 / 3.5.2016" states: The type T of the case expression (case variable) may also be a record or pointer type. Then the case labels must be extensions of T, and in the statements Si labelled by Ti, the case variable is considered as of type Ti. That's why the case label | Sqlite.Error: works and the case label | Sqlite.TError: does not. But now when I think about it the "pointerness" should not be determined by the case label but by the type of the case variable; otherwise it would even be possible to get an address of a record which is not intended. I will add clarifications to the spec and likely change the compiler.

rochus-keller commented 2 years ago

I just uploaded a new specification and compiler version which no longer allows mixture of pointer and record types in IS expressions, as well as in type CASE and WITH statements, after doing experiments with the Ѵishap compiler and having a look at the source code of Wirth's Oberon-07 compiler. The said compilers don't allow this mixture. Apparently extension relation is limited to pointer-pointer or record-record relations. Natural language has its limitations when used in formal specifications; unlike mathematical formalisms, readers cannot be expected to assume the same (implicit) assumptions as the author of the very minimal set of rules; I have now increased the degree of redundancy and made the aforementioned facts explicit.

And thank you very much for this test case which was very useful!

tenko commented 2 years ago

Excellent. Glad to be to help. It now gives an error with mixed types.