[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ooc-m68k-960119



>  Date: Fri, 19 Jan 96 20:33:55 +1000
>  From: Frank Copeland <fjc@wossname.apana.org.au>
>  
>  Hi all,
>  
>  I've just uploaded a new version of the AmigaOS backend for OOC. It has
>  been built from the ooc-960117 sources, and tested by compiling all the
>  source code for OOC itself, OOB and the test modules. Only a couple of
>  problems arose:
>  
>    * When compiling frontend/first_steps/Predef.Mod, OOC halts with a NIL
>      pointer trap in module GateReduction, line 111, col 42. This occurs
>      while compiling the procedure Predef.TestHalt.
Fixed it.  I should remember to try to compile these little modules
myself... I'll put an update on cognac next week wednesday or so.
Promised :-).

>  
>    * The parsing of external code declarations appears to be broken. When
>      compiling frontend/Test/Ext.mod the following errors are reported:
>  
>        12:123 ']' expected
>        12:139 ';' expected

The front-end has no code to parse external declarations.  It will
only accept an empty pair of brackets.  So this isn't a bug.  It's a
huge part of missing code, mostly on the back-end side.  Just in case
you want to start working on this: I've extended the doc/Modifiers
text.  It now includes some motivating blurb, and I've splitted
procedure modifiers into two parts.  I'll append a copy to this reply.

>  
>  A bug in Oberon-A's OC was discovered while doing all of this, and the
>  fixed version (OC 5.39) will be uploaded to the artworks ftp site in the
>  next day or so.
Funny how this project unveils a whole bunch of bugs in both o2c and
Oberon-A.  Somewhat annoying though to have to release a new version
of o2c every month or so.  :-(


------------------------------------------------------------------------
#	$Id: Modifiers,v 1.4 1996/01/19 16:14:45 oberon1 Exp $	

There are some points to consider when interfacing to foreign
languages.  
  First of all the access to foreign libararies (object files,
modules, etc) should be as transparent as possible to the Oberon-2
programmer.  Using a foreign type, reading and writing to foreign
variables, and calling a foreign procedure should look exactly as if
these objects were normal Oberon-2 entities.
  Therefore all foreign constructs have to be mapped to their Oberon-2
counterparts.  Thas is, a C type has to be mapped onto an Oberon-2
type, a C function has to be onto an O2 procedure, etc.  This
projection is handled by some kind of definition modules, which in
turn can be imported into a O2 module and used just like any other
module.
  The problems arise whenever the mapping of foreign construct onto
O2 construct isn't perfect, ie one of them carries more information
resp. attributes than the other.  An example for this is the O2
pointer type, which is associated with a type tag (for records) or
an array's length (for open arrays).  The C pointer, on the other
hand, is simply an address.  
  For this reason the mapping foreign --> O2 has to be extended to
cover semantic attributes that are not part of Oberon-2.  Since it
isn't desirable to extend the language Oberon-2, eg, to cover a C like
struct type, this has to be done by providing a mechanism to modify
the semantics of standard O2 constructs.  The idea is to map, eg, a C
struct onto a O2 record that is marked as having no associated type
descriptor.  I'll call this additional attributes `modifiers'.

Modifiers are either applied to an object (variable, procedure,
parameter, etc) or to a type (record, array, formal parameter list,
etc).  Modifiers are syntactically defined as a left bracket "[",
followed by a implementation-defined list of keywords (or something
more complex), and a right bracket "]".  It is up to the back-end to
define what may appear inside the brackets and how the contents have
to be interpreted.  The placement of a modifier determines with which
O2 object it is associated.

Examples:
TYPE
  S = RECORD [NOT_EXTENSIBLE, NO_DESCRIPTOR]
        ...
      END;
Would define a C like struct as a kind of record that cannot be
extended and that has no associated type descriptor.

PROCEDURE [CODE] foo*;
  4E, 05, 56, ...
END foo;
Would declare a procedure named `foo' whose body is defined by the
byte codes.


Other possible modifiers:
[Note that this is a list of modifiers that may be of some use.  It's
certainly not complete.  Some of them may be better implemented as
pragmas, like <* Initialize := TRUE *> ).  --mva ]

Module modifier
  ["callingConvention"] EXTERNAL [linking info]
  like
  ["C"] EXTERNAL ["lib.o"]
[This is the Oakwood syntax, I'd prefer to drop the addtional brackets
to left and the right of EXTERNAL.  --mva ]

Type modifier
  RECORD
    UNION: Allocate fields as if the record is a union type
    NOT_EXTENSIBLE: This record can't be another one's base type
    NO_DESCRIPTOR: This record has no associated type descriptor,
      type tests are applicable
  ARRAY 
    NO_DESCRIPTOR: Array has no type descriptor
  POINTER
    NO_LENGTH: No length information available on open array base
      type 
    NO_TAG: Record base type has no type tag
  Formal parameter list
    PASS_ON_STACK: Parameters are pushed onto the stack
    RIGHT_TO_LEFT: Parameters are pushed in reversed order 

Procedure modifier
  CODE: Procedure is a code procedure
  CALLBACK: (don't know what this is for)

Parameter modifer
  NO_LENGTH: Open array parameter isn't passed together with
    length info 
  NO_TAG: Variable record parameter isn't passed together with
    type tag
  NIL_COMPATIBLE: The value NIL can be passed to the VAR
    parameter 
  CONST: deny write access to this parameter

Variable modifiers
  VOLATILE: Each access/update of this variable has to be read
    from/written to memory and can't be kept in register
  CLEAR: initialize variable to zero  (there is already a pragma
    implemented for this)


--------
Implementation stuff:

At the places of `Modifiers' the parser will call the procedure
`ObjectModifiers' with the object under construction as first parameter 
and TRUE as second parameter:
  Module = "MODULE" ident Modifiers ";" ...
  VarDecl = IdentDef Modifiers {"," IdentDef Modifiers} ":" Type.
  ProcDecl = "PROCEDURE" ["^"] [Receiver] Modifiers IdentDef [FormalPars] ";" ...
  FPSection = ["VAR"] ident Modifiers {"," ident Modifiers} ":" Type.

When all information for the object has been collected (and the
object's internal representation is complete), `ObjectModifiers' will
be called again on this object, this time with FALSE as second
parameter, to do semantic checks.  The modifier has to be parsed
completely by the first call, the second call shouldn't parse anything
at all.
  Note 1: Although modifiers of procedures appear before the procedure
name, the IdentDef part of the declaration has already been parsed at
the time `ObjectModifiers' is called (the parser will first skip the
[..] part, read the IdentDef, and set the scanning position back to
the initial "[").  The object passed to `ObjectModifiers' will have
the correct name and the export flag set.
  Note 2: A procedure has actually two sets of modifiers.  One
associated with the procedure entity itself, the other with the
procedure's formal parameter list (see below).  The latter is relevant
for the procedure's type (eg when assigning a procedure to a
variable).

--------

At the places of `Modifiers' the parser will call the procedure
`StructModifiers' with the type under construction as first parameter 
and TRUE as second parameter:
  FormalPars = Modifiers "(" [FPSection {";" FPSection}] ")" [":" Qualident].
  Type = Qualident | 
         "ARRAY" Modifiers [ConstExpr {"," ConstExpr}] "OF" Type | 
         "RECORD" Modifiers ["("Qualident")"] 
                                FieldList {";" FieldList} "END" | 
         "POINTER" Modifiers "TO" Type | 
         "PROCEDURE" [FormalPars].  

When all information for structure has been collected (and the type's
internal representation is complete), but before StdTypes.StructAlloc
ist called, `ObjectStruct' will be called again on this structure,
this time with FALSE as second parameter, to do semantic checks.  The
modifier has to be parsed completely by the first call, the second
call shouldn't parse anything at all.
------------------------------------------------------------------------

-- mva