vishapoberon / compiler

vishap oberon compiler
http://oberon.vishap.am
GNU General Public License v3.0
186 stars 25 forks source link

Spurious error message with anonymous array parameters #50

Closed diegosardina closed 7 years ago

diegosardina commented 7 years ago

PROCEDURE Test (v: ARRAY 5 OF REAL); BEGIN END Test;

voc returns:

err 200 not yet implemented

but it is clearly a syntax error.

dcwbrown commented 7 years ago

Turns out it really is unimplemented. Here are the relevant lines from the Oberon-2 spec:

FormalPars  =  "(" [FPSection {";" FPSection}] ")" [":" Qualident].
FPSection  =  [VAR] ident {"," ident} ":" Type.
Receiver = "(" [VAR] ident ":" ident ")".
Type  =  Qualident
| ARRAY [ConstExpr {"," ConstExpr}] OF Type 
|  RECORD ["("Qualident")"] FieldList {";" FieldList} END
| POINTER TO Type
|  PROCEDURE [FormalPars].

So while any result type of a procedure must be a name, parameters are theoretically allowed to be full type definitions. Indeed

PROCEDURE Test (VAR v: ARRAY 5 OF REAL); BEGIN END Test;

compiles without error. What is unimplemented here is the copying of the value parameter to a local stack variable.

diegosardina commented 7 years ago

It looks like that Oberon and Oberon-2 have different grammars, I'm more an Oberon user, for this reason I didn't look at the latter.

From Oberon report:

FormalParameters = "(" [FPSection {";" FPSection}] ")" [":" qualident]. FPSection = [VAR] ident {"," ident} ":" FormalType. FormalType = {ARRAY OF} qualident.

Oberon doesn't expect a type declaration but a qualident (or an open array parameter).

I guess in Oberon-2 the grammar was made flexible for later extensions (like OberonX) or just to give the possibility to have some parameters with structural equivalence by some dialects.

But plain Oberon-2 doesn't support this, neither with VAR (it needs to be fixed).

Leaving this possibility is ok (the code is already there) but the message "not yet implemented" is spurious, it gives the idea that one day it will be implemented. At least a better message is needed.

dcwbrown commented 7 years ago

Could you clarify your comment 'But plain Oberon-2 doesn't support this, neither with VAR (it needs to be fixed).'? - Did you main 'plain Oberon' as in original Oberon (or indeed Oberon-07)? Or are we working with different Oberon-2 specs? (The quoted spec I gave was from the Oberon-2 report, sorry I wasn't clear about that.)

diegosardina commented 7 years ago

Sorry, what I said maybe is misleading.

With 'plain Oberon-2' I mean Oberon-2 with no extensions or dialects of Oberon-2.

In Oberon-2 and OP2 they left some level of flexibility for extensions and dialects, for example Component Pascal (cp compilers are based on OP2) has pointer type parameters compatible by structure. It was easy for them to modify OP2 and achieving this with no grammar change.

But Oberon-2 follows the same rules of Oberon for parameter passing.

PROCEDURE Test (VAR v: ARRAY 5 OF REAL); BEGIN END Test;

Although it compiles, this procedure is unusable because no variable will match that type.

For what I remember neither Modula-2 permits anonymous structures as parameters.

diegosardina commented 7 years ago

Oxford Oberon-2 raises a warning instead:

line 3: warning -- you should name this parameter type, or else no actual parameter will match

Both for value and variable parameters.

This is the best compromise in my opinion, because: 1) it respects Oberon-2 grammar by expecting a type declaration; 2) it warns that no variable will match that type, respecting Oberon-2 semantics.

In Oberon it is clearly a syntax error, but it seems that there is no switch for it.

dcwbrown commented 7 years ago
Although it compiles, this procedure is unusable because no variable will match that type.

Thanks for explaining - Yes - Try as I might, I can see no way of passing a parameter to such a parameter.

So I tried this in Component Pascal, and found that that compiler accepts the parameter declarations:

  PROCEDURE xx (v: ARRAY 5 OF REAL); BEGIN END xx;

and

  PROCEDURE xx (VAR v: ARRAY 5 OF REAL); BEGIN END xx;

without complaint.

But is then unable to call either procedure, correctly complaining either about assignment compatibility in the pass by value case, or type identicalness in the var case.

And indeed, the Modula spec I have (Wirth 1980) expects the parameter types to be qualidents, not types.

So the next question is - what should the error message be?

Is there an existing compiler that correctly identifies this, and if so what error number and text does it produce?

If not, what would be a concise but not cryptic message? It is syntactically correct but semantically useless. A bit like unreachable code perhaps. 'Useless parameter type' would have the right meaning but likely just confuse the reader :-).

Ah! You have just added a comment that answers my exact question - synchronicity or something.

I like that message.

Thanks -- Dave.

dcwbrown commented 7 years ago

I've just commited a fix for this in the ADRINT branch.

diegosardina commented 7 years ago

Thank you :-)