Language Agnostic API for P2 HAL Implementations

DavidZemonDavidZemon Posts: 2,817
edited 2019-03-05 - 03:15:36 in Propeller 2
Wouldn't it be cool if every (major/large) library for the Propeller 2 implemented a similar API? Of course it would - then jumping from one language to another would only be as hard as learning the new syntax rather than learning both a syntax and a new library API. It's going to be hard. Without a dictator, there will be religious wars over what is the "right" or "best" signature for a certain method. If there was a dictator, there would be a mutiny. But if we can make it happen, if we can agree on a single language-agnostic API that HAL (hardware abstraction library) authors can implement (or at least, draw inspiration from), wouldn't that be COOL!?

I think now is the time to start talking about this. We're early enough that very little work has been done toward HAL implementations yet far enough into P2 development that we have a variety of tools at our disposal that will let us start implementing the APIs across different languages, and trying them out to see what works and what doesn't.
(I think Peter's ROM code probably has the most work put into it, and hopefully we can learn something from the Forth API, but I don't know how well that will translate to stack-based languages)

I would propose using a slightly modified Spin syntax to describe this API. This should be sufficiently legible by anyone with the most basic of programming experience, while also providing the necessary information to translate to other languages
function_name(parameterName1, parameterName2) : returnType  # Any extra description necessary, such as what the return value is and whether or not exceptions might be raised

Note that parameters do not have types associated with them in this psuedo code, and the return type should be as broad as possible. I can imagine valid types being limited to "boolean", "string", "number" or the name of a type described elsewhere in the API (for instance, maybe a function returns an instance of a UsbBus, or something like that).

An example might look like this:
start_pwm(pin, frequency, duty) : number  # Returns an error code if any parameters are invalid

You could then translate this to C, C++ and Python as (these are just ideas - don't get caught up on my implementation of the above API):
error_t start_pwm(const uint32_t pin, const uint32_t frequency, const uint8_t duty);
class Pin {
  public:
    Pin(const uint8_t pinNumber);
    void start_pwm(const uint32_t frequency, const uint8_t duty) const; // Throws an exception if any parameters are invalid
};
class Pin:
  def __init__(pinNumber)
  def start_pwm(frequency, duty)  # Raises an exception if any parameters are invalid

In the spirit of open source software, perhaps this API can be documented in a Markdown file (or a collection of files) and stored in GitHub, on github.com/parallaxinc. This allows us to have fights discussions over new proposals via the Pull Request system and avoids the problem of one person leaving the community and preventing access to edit the top forum post anymore.

What do you guys think? Is this feasible? Is it a pipe dream that can never happen? Most importantly, if such a document existed and contained an API with functions that performed a task you wanted to implement, WOULD YOU FOLLOW IT even if you disagreed with it? Would you accept that conformity is better than perfection? Or would you simply see the API and think "well that's dumb, they should have done it this way," and proceeded to write your own HAL with a completely different API?

Let me also lay down some of extra "guidelines" I think should be followed:

Language standards come first. If a language has a standard (think Python's PEP) or overwhelming convention, always follow that over any convention in the language agnostic API. For instance, I used camelCase for parameter names but PEP dictates underscores. The Python implementations should therefore use underscore for all parameter names.
On a similar note, C and Spin don't have exceptions and therefore must report errors through a return code (please don't crucify me if that's incorrect about Spin... I haven't written Spin in a long time). However, the Python implementation should use the Pythonic way of handling errors: raise an exception and DO not return an "error code."


If this gains traction, I will update this first post with any pertinent information.
David
PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
CI Server: https://ci.zemon.name?guest=1
«1

Comments

  • Thanks for kicking this off, David.

    Its clear that things are starting to move with other language options, which makes it a good time to at least discuss. I'm sure where will be a wide variety of opinions, and consensus might be hard to reach in all areas, but lets have a go, particularly around smartpins
  • I am interested in this idea. I had to look up what your are discussing. Very interesting. I would like to learn more about this. So I would be a learning participant. Would be fascinating as


    as Mr. Spock would say.
    Please send me some links so I can understand more.

    Thanks

    Martin
    “Light thinks it travels faster than anything but it is wrong. No matter how fast light travels, it finds the darkness has always got there first, and is waiting for it.”
    “You only live twice:
    Once when you are born
    And once when you look death in the face”
  • jmgjmg Posts: 13,911
    edited 2019-03-05 - 04:29:55
    DavidZemon wrote: »

    An example might look like this:
    start_pwm(pin, frequency, duty) : number  # Returns an error code if any parameters are invalid
    
    error_t start_pwm(const uint32_t pin, const uint32_t frequency, const uint8_t duty);
    

    The broad idea has merit, but I guess it depends on how close you want to be to the silicon, and how much code you want inside the function calls.

    My preference would be to start from the Smart Pin Docs, and code APIs from there up, so you get full silicon coverage.

    Other APIs could call those base ones, if that was required.

    Let's look at the smart pin DOCs
    "%01001 = PWM sawtooth

    This mode overrides OUT to control the pin output state.
    X[15:0] establishes a base period in clock cycles which forms the empirical high-time and low-time units.
    X[31:16] establishes a PWM frame period in terms of base periods.
    Y[15:0] establishes the PWM output value which gets captured at each frame start and used for its duration. It should range from zero to the frame period.
    A counter, updating at each base period, counts from one up to the frame period. Then, Y[15:0] is captured, IN is raised, and the process repeats.
    At each base period, the captured output value is compared to the counter. If it is equal or greater, a high is output. If it is less, a low is output. Therefore, a zero will always output a low and the frame period value will always output a high.
    During reset (DIR=0), IN is low, the output is low, and Y[15:0] is captured.


    So the first problem is frequency is not a natural parameter here, nor is duty. Also uint8_t duty is going to be too coarse for many uses, and does not use all the silicon capability.


    I also find the Smart Pin docs a little obtuse, so a formula based description in the API would help explain to users what they need to fill out, for what outcome.

    To me, the natural parameters here, which are pretty much chosen by the HW of the Smart Pin itself, are
    u6   PWM_Pin
    u16  PWM_Div     PWM_Clk = SysCLK/PWM_Div
    u16  PWM_Per     PWM_Hz  = SysCLK/(PWM_Div * PWM_Per);  PWM_counter =  Sawtooth 1..PWM_Per
    u16  PWM_Comp    PWM_Pin = (PWM_Comp >= PWM_counter)   (0 : LOW, PWM_Comp=PWM_Per : Hi  1..PWM_Per-1 = Pulses) 
    
    Example :  ~ 1kHz PWM period, 30.00% Hi, from 180MHz SysCLK, best granularity  ->  
    PWM_Div  = 3;  
    PWM_Per  = 60000;  
    PWM_Comp = 18000;  
    PWM_Hz -> 180M/(3*60000) = 1.0000kHz  PWM_Hi -> 18000 * 3/180M = 300.0us
    

    I think PWM_Per = 0xffff is legal and gives PWM_Pin = HI, no matter what PWM_Per is set to. ie that's PWM_Comp >= PWM_Per : Hi

  • And expect some dumb questions in the beginning.
    “Light thinks it travels faster than anything but it is wrong. No matter how fast light travels, it finds the darkness has always got there first, and is waiting for it.”
    “You only live twice:
    Once when you are born
    And once when you look death in the face”
  • @jmg, absolutely. I would expect to have very low level functions that do nothing more than write a 32 bit value to a register, and then progressively higher level ones, up to maybe "drive(direction, power)". A couple months ago I started playing around with what a C HAL might look like:
    https://github.com/DavidZemon/HelloP2GCC/blob/master/common.h

    And I agree about 8-bits not being precise enough for duty cycle in a general purpose library. I was thinking 0-100% in 1% increments, but finer granularity will almost certainly be appreciated. This is, of course, why it's important that fine details like bit widths be left out of the language agnostic version.

    @pilot0315 questions are welcome :) would you mind being specific about what it is you need help understanding? I don't have any links to share in this case because I've not heard of anyone ever attempting or even discussing something like this before (that should probably be a big red flag right there... But let's just assume I'm young, naive, and ill informed and that someone else HAS in fact done this before and succeeded at it... Because uncharted territory is scary)
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • It'd also be nice to have versions that take the same parameters as the normal version but output values for you to manually feed to w[r,x,y]pin instead of doing it itself. It would facilitate precomputing and storing settings once ahead of time to allow more efficient switching between modes.
  • jmgjmg Posts: 13,911
    DavidZemon wrote: »
    @jmg, absolutely. I would expect to have very low level functions that do nothing more than write a 32 bit value to a register, and then progressively higher level ones, up to maybe "drive(direction, power)". ...

    And I agree about 8-bits not being precise enough for duty cycle in a general purpose library. I was thinking 0-100% in 1% increments, but finer granularity will almost certainly be appreciated. This is, of course, why it's important that fine details like bit widths be left out of the language agnostic version.
    I'm not sure I'd call bit-widths something to be left till later. They can be an important indicator of the smart-pin mode ability, Likewise, the equations remove confusion around outcomes...

    As an example, a recent discussion for Servo pulse control via smart pin, had me reaching for the natural PWM - but that has 16b fields so limits the granularity.
    Someone else spotted a sub mode in another smart pin mode, that allowed one-shot pulses to 32b precisions.
    If those bit-widths are too hidden, users get no guides of the underlying silicon limits and capabilities.


  • Basically I would like to follow the thread with good documentation to follow what is going on. I looked up the subject and have no clue but can learn fast. This seems very interesting to me. As a linguist of spoken languages and have a command of several code languages I am very interested in this subject.
    Just keep me in a beginners loop so I can get up to speed. And understand the basics.
    Thanks
    “Light thinks it travels faster than anything but it is wrong. No matter how fast light travels, it finds the darkness has always got there first, and is waiting for it.”
    “You only live twice:
    Once when you are born
    And once when you look death in the face”
  • Once I get the idea and understand I may be able to participate.
    “Light thinks it travels faster than anything but it is wrong. No matter how fast light travels, it finds the darkness has always got there first, and is waiting for it.”
    “You only live twice:
    Once when you are born
    And once when you look death in the face”
  • @DavidZemon : This is an *excellent* idea, thank you for starting the thread. I definitely think a language agnostic API that exposes the P2 hardware features is something we need, and I'll do what I can to support it (assuming we can come up with some reasonable proposal).

    Here are some of my thoughts on the subject, in no particular order:

    - We may actually want two layers: a HAL (hardware abstraction layer) that hides/abstracts hardware details, and a lower level (I'll call it a hardware interface layer, or HIL) that directly exposes the P2 hardware. As an example, in the HAL we might have a function like "set_system_frequency(freq)" that sets the system clock to a requested frequency. This would calculate an appopriate P2 clock mode and call the lower level HIL function "clkset(mode, freq)" which would issue hubset instructions to actually do the change.

    What I'm envisioning is that HIL calls would map to 1 or at most a few P2 instructions, but HAL ones might be more complicated. The idea is that code written to the HAL could run on P1, P2, or future chips (within reason, of course; if a chip doesn't support ADC then HAL analog to digital conversion functions will report an error). The HIL would be pretty much processor specific, or close to it.

    - I think the HAL and HIL function proposals probably should include types for parameters and return objects. Some languages (like Spin and Python) may not need them, but other languages (like BASIC and C) do, and they could be useful for documentation purposes as well. Incidentally, fastspin accepts but does not require type annotations like "=long" or "=@byte" on parameters and return values.

    - I'm not a Tachyon expert at all, but I think @Peter Jakacki has probably covered some of this ground already, and any FORTH words he already has defined would probably be a good starting point.

    - In general I think if we can get Tachyon, p2gcc, and fastspin to support some API then it's probably going to become a de-facto standard. Obviously it would be good to hear from @cgracey about his Spin2 plans as well. Hopefully he'll contribute his ideas and/or support what we come up with.
  • I'm very happy to see such interest :)

    What about object names? Is it worth making the API object oriented? If spin2 supports or will support multiple instances of the same object, I'd say yes. Otherwise, I'd say make the psuedo code procedural and let OO languages convert to objects.

    I'm happy to use types, though definitely surprised. What do you think of switching to C syntax? That lets us be precise with const and pointers and references where necessary.
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • Great idea!
    Watching with interest :smiley:
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • DavidZemon wrote: »
    What about object names? Is it worth making the API object oriented? If spin2 supports or will support multiple instances of the same object, I'd say yes. Otherwise, I'd say make the psuedo code procedural and let OO languages convert to objects.
    Spin has always supported multiple instances of the same object, but the original Spin was very limited with what you could do with them (there was no way to pass pointers to an object; the only option was declaring an array of objects and then passing an index into that array, but that only worked within the same source file). I think @Dave Hein found some work-arounds that let you have method and object pointers. Fastspin has object pointers built in to the language as an extension, and I think Chip was planning to do something similar in his compiler.

    That said, a procedural API would be more generally applicable than an object oriented one; FORTH, for example, doesn't have any idea of objects. So probably we should start there.
    I'm happy to use types, though definitely surprised. What do you think of switching to C syntax? That lets us be precise with const and pointers and references where necessary.

    I think C syntax would work well. The only restriction C has is that it only allows single return values, whereas fastspin/spin2 allow multiple return values. But only a few languages support multiple returns, and if we really have to we can get something similar in C by returning structs (or having output-only pointer parameters, but I think that's ugly and hurts optimization).

  • ersmith wrote: »
    DavidZemon wrote: »
    What about object names? Is it worth making the API object oriented? If spin2 supports or will support multiple instances of the same object, I'd say yes. Otherwise, I'd say make the psuedo code procedural and let OO languages convert to objects.
    Spin has always supported multiple instances of the same object, but the original Spin was very limited with what you could do with them (there was no way to pass pointers to an object; the only option was declaring an array of objects and then passing an index into that array, but that only worked within the same source file). I think @Dave Hein found some work-arounds that let you have method and object pointers. Fastspin has object pointers built in to the language as an extension, and I think Chip was planning to do something similar in his compiler.

    That said, a procedural API would be more generally applicable than an object oriented one; FORTH, for example, doesn't have any idea of objects. So probably we should start there.
    I'm happy to use types, though definitely surprised. What do you think of switching to C syntax? That lets us be precise with const and pointers and references where necessary.

    I think C syntax would work well. The only restriction C has is that it only allows single return values, whereas fastspin/spin2 allow multiple return values. But only a few languages support multiple returns, and if we really have to we can get something similar in C by returning structs (or having output-only pointer parameters, but I think that's ugly and hurts optimization).

    Multiple return values is a really good point. Let's have the API allow for that. Python supports it too, and I fully expect the C implementation to use "output parameters" when it needs to both return an error code and return a value. So now we're looking at something like this for the language-agnostic part:
    function_name(modifiers type parameter1Name[, modifiers type paramter2Name]) : returnType1[, returnType2] // Comments
    

    Now... I'm starting to have problems with specifying types. I'm tempted to write the following API function
    start_pwm(const pin_t pin, const uint32_t frequency, const uint32_t dutyCycle) : None // No return value
    

    and then be 100% okay with specifying no return value, because pin_t would enumerate each and every one of the 64 pins, therefore making it impossible to pass in any invalid values. But what does a dynamically typed language like Spin or Python do? I'm starting to think, again, that the language-agnostic part of this API should really just be focused on:

    1. What functions are exposed
    2. What are the parameters for those functions
    3. What values and errors might the functions return
    4. How will modules be organized (procedural and OO languages must have some kind of organization, whether that's just folders, classes, packages, file names, etc doesn't matter)

    What about a different idea. What if return values are specified separately from errors? What if a "!" in the signature says "everything after me is an error scenario that might (or might not) need to be handled"
    start_pwm(pin, frequency, dutyCycle) : None ! invalidArguments
    

    This could expand to the following C code:
    /**
     * @brief Start a PWM signal
     *
     * @param[in] pin Pin number that will generate the PWM signal
     * @param[in] frequency Frequency (in Hz) for the signal
     * @param[in] dutyCycle Duty cycle, as a ratio of `dutyCycle/UINT_MAX`, for the PWM signal
     */
    void start_pwm(const pin_t pin, const uint32_t frequency, const uint32_t dutyCycle);
    

    Note that C doesn't need an error codes because the pin can be fully enumerated and therefore catching any invalid arguments at compile time. However, the error does need to be handled in Python:
    class Pin(object):
      def __init__(self, pinNumber: int):
        """
        :param pinNumber Pin number (1-indexed) to be used
        :raises Exception: If `pinNumber` greater than maximum number of pins (64)
        """
        pass
    
      def start_pwm(frequency: int, dutyCycle: float) -> None:
        """
        :param frequency Frequency (in Hz) for the signal
        :param dutyCycle Duty cycle as a percentage from 0.0 to 100.0
        :raises Exception: If duty cycle is less than 0 or greater than 100
        """
        pass
    
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • DavidZemon wrote: »
    Multiple return values is a really good point. Let's have the API allow for that. Python supports it too, and I fully expect the C implementation to use "output parameters" when it needs to both return an error code and return a value. So now we're looking at something like this for the language-agnostic part:
    function_name(modifiers type parameter1Name[, modifiers type paramter2Name]) : returnType1[, returnType2] // Comments
    

    Now... I'm starting to have problems with specifying types. I'm tempted to write the following API function
    start_pwm(const pin_t pin, const uint32_t frequency, const uint32_t dutyCycle) : None // No return value
    

    and then be 100% okay with specifying no return value, because pin_t would enumerate each and every one of the 64 pins, therefore making it impossible to pass in any invalid values.

    No, let's not rely on the type checking to prevent errors -- even in C the programmer could cast an illegal value to a pin_t and pass it to the function. For that matter, I would strongly suggest that we should stick to a small set of types that will be available for all languages (things like "int32_t", "uint8_t", "string", or pointers to those). Some languages (e.g. assembler) don't really have types, and we also don't want to burden the reader of the documents with having to learn a bunch of P2 API specific types like "pin_t".

    I really wouldn't sweat the details of how the pseudo-code declarations look; we can always change those later. Just pick something simple that should be widely supported (like C declarations) and write the API that way. We can always change it later if we get stuck. Remember Knuth's adage: "Premature optimization is the root of all evil".

  • jmgjmg Posts: 13,911
    edited 2019-03-05 - 20:10:38
    ersmith wrote: »
    @DavidZemon : This is an *excellent* idea, thank you for starting the thread. I definitely think a language agnostic API that exposes the P2 hardware features is something we need, and I'll do what I can to support it (assuming we can come up with some reasonable proposal).

    Here are some of my thoughts on the subject, in no particular order:

    - We may actually want two layers: a HAL (hardware abstraction layer) that hides/abstracts hardware details, and a lower level (I'll call it a hardware interface layer, or HIL) that directly exposes the P2 hardware. As an example, in the HAL we might have a function like "set_system_frequency(freq)" that sets the system clock to a requested frequency. This would calculate an appopriate P2 clock mode and call the lower level HIL function "clkset(mode, freq)" which would issue hubset instructions to actually do the change.

    What I'm envisioning is that HIL calls would map to 1 or at most a few P2 instructions, but HAL ones might be more complicated. The idea is that code written to the HAL could run on P1, P2, or future chips (within reason, of course; if a chip doesn't support ADC then HAL analog to digital conversion functions will report an error). The HIL would be pretty much processor specific, or close to it.

    - I think the HAL and HIL function proposals probably should include types for parameters and return objects. Some languages (like Spin and Python) may not need them, but other languages (like BASIC and C) do, and they could be useful for documentation purposes as well. Incidentally, fastspin accepts but does not require type annotations like "=long" or "=@byte" on parameters and return values.
    I agree, that's pretty much what I said above, where that HIL is close to the silicon. Certainly code is simple, mostly merge, with minimal/no mathsops.

    I think that HIL should be coded first, to give full access to smart pin modes, and it also guides HAL work, as some things will be more natural than others.

    Taking the PWM example, since it is appearing here many times, the HIL actually needs 4 parameters, and does not 'think' in Hz units.
    Instead, it accepts u16 dividers and compares, and avoids needing to know any SysCLK.
    An HAL that tries to define just Hz,Duty has to know SysCLK, and also needs to take a guess on the split of 2 u16 values that are chained to deliver an approximation to the user requested Hz.
    The HIL u16 Compare value knows it is relative to the u16 Period value, whilst an HAL that passes DUTY needs to remember what split was chosen for Hz, to scale the duty, and the decimal point location is unclear here too.
    The biggest problem is Hz,Duty gives the illusion of portability and precision, whilst what you actually get will vary with language library implementation decisions.


    ersmith wrote: »
    - I'm not a Tachyon expert at all, but I think @Peter Jakacki has probably covered some of this ground already, and any FORTH words he already has defined would probably be a good starting point.

    TAQOZ already has a HIL that is close the the silicon, here is a PWM example : Reverse polish, so defines 47 then PIN to map which pin, and passes 3 parameters to Smart pin Sawtooth PWM mode.
    This is 4/8 = 50% duty, SysCLK/1/8
    '47 PIN 4 8 1 SAW'
    
  • I'd definitely support this idea, David. An effort towards something similar (spin-specific, though) was started for the P1 (the spin-standard-library). I think more effort was put into having everything in the same spot and created with a set of formatting guidelines, though I believe standardizing API's where possible like you're talking about, was a future plan that unfortunately never really came to be. I've continued to use it though, and In all the drivers I've been working on, I've realized how much it makes sense to try to write as much of them the same way as possible - it really does make development easier. I've started to implement an idea I had for a "build standard", so everything I've written would get updated incrementally to the current build standard version - had hoped to eventually work it all back into the s-s-l.
    I'd follow a standard if we were to implement one.

    Cheers,
    Jesse
    --
    WIP Spin drivers for various devices: LSM9DS1 | US2066 | MLX90621 | SHT3x | SSD1306 (P1, P2) | TCS3x7x | MAX31856 | BMP280 | TMC2130 | nRF24L01+ | MLX90614 | MAX9744 | DS28CM00 | TSL2591 | CC1101 | SX1231 | LM75 | DS18B20 | Si7021 | INA219
    Use with spin-standard-library (fork)
  • ersmith wrote: »
    DavidZemon wrote: »
    Multiple return values is a really good point. Let's have the API allow for that. Python supports it too, and I fully expect the C implementation to use "output parameters" when it needs to both return an error code and return a value. So now we're looking at something like this for the language-agnostic part:
    function_name(modifiers type parameter1Name[, modifiers type paramter2Name]) : returnType1[, returnType2] // Comments
    

    Now... I'm starting to have problems with specifying types. I'm tempted to write the following API function
    start_pwm(const pin_t pin, const uint32_t frequency, const uint32_t dutyCycle) : None // No return value
    

    and then be 100% okay with specifying no return value, because pin_t would enumerate each and every one of the 64 pins, therefore making it impossible to pass in any invalid values.

    No, let's not rely on the type checking to prevent errors -- even in C the programmer could cast an illegal value to a pin_t and pass it to the function. For that matter, I would strongly suggest that we should stick to a small set of types that will be available for all languages (things like "int32_t", "uint8_t", "string", or pointers to those). Some languages (e.g. assembler) don't really have types, and we also don't want to burden the reader of the documents with having to learn a bunch of P2 API specific types like "pin_t".

    I really wouldn't sweat the details of how the pseudo-code declarations look; we can always change those later. Just pick something simple that should be widely supported (like C declarations) and write the API that way. We can always change it later if we get stuck. Remember Knuth's adage: "Premature optimization is the root of all evil".

    Just want you to know that I did read your response yesterday and my gut reaction is to disagree. I'll hold off a lengthy response until my brain can come to terms with my gut. Maybe I'm just being stubborn and need time to come around.

    ALSO! Anyone have a name suggestion for this thing?
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • DavidZemon wrote: »
    Just want you to know that I did read your response yesterday and my gut reaction is to disagree. I'll hold off a lengthy response until my brain can come to terms with my gut. Maybe I'm just being stubborn and need time to come around.

    Not sure which part you disagree with, but if it's the "let's not use user defined types in the API" I wasn't saying that we should avoid them in any particular implementation. If you want to define types for everything in PropWare go ahead! I just meant that in the language agnostic specification we shouldn't assume that the language has the ability to define and/or enforce types, and should use just a minimal set of types that are common to all languages.
  • DavidZemonDavidZemon Posts: 2,817
    edited 2019-03-06 - 19:17:08
    ersmith wrote: »
    DavidZemon wrote: »
    Just want you to know that I did read your response yesterday and my gut reaction is to disagree. I'll hold off a lengthy response until my brain can come to terms with my gut. Maybe I'm just being stubborn and need time to come around.

    Not sure which part you disagree with, but if it's the "let's not use user defined types in the API" I wasn't saying that we should avoid them in any particular implementation. If you want to define types for everything in PropWare go ahead! I just meant that in the language agnostic specification we shouldn't assume that the language has the ability to define and/or enforce types, and should use just a minimal set of types that are common to all languages.

    That's a little bit of it, but I was already on the same page with "i can just write propware my own way" because that's a small enough deviation that I'm not concerned about it.
    What I was more concerned with was whether or not to even specify types in the language-agnostic API (LAAPI? I'm getting really tired of typing that out). It comes down to: where do we want to draw the line. How much type information do we want to provide in the LAAPI? You seem to want to draw the line as basic primitive types (primitive for any language other than C, that is :wink: ). But there are multiple steps higher and lower level. You could be more specific and say "basic primitive types + modifiers like const" and less specific and say something like "only JSON types" which limits you simply to number/bool/string/object and nothing more. Or a step further in each direction, "all C/C++ data types" or "no data types."

    I'm having a hard time getting behind anything other than no types or JSON types in the LAAPI ("lap-ee"? "L-A-A-P-I"? "lae-pee"? life is hard...). I think anything more specific than that should be a decision based on the language and no attempt should be made to standardize that across different languages.

    Btw, I just want to re-iterate one thing: this idea of mine does include language-specific APIs as part of the standard. The LAAPI by itself is not the entire goal. I want a repository with the LAAPI and language-specific APIs for a few different languages. What my idea explicitly excludes is any executable/compilable code. Just APIs/prototypes/signatures/whatever you want to call them.

    ...................................
    ...................................

    Also, I had a separate idea this morning. Once this thing reaches a point where people start writing their own HALs that implement the standard API, it's almost certain that someone will create something that matches some aspect of the standard but not all. It would be GREAT if we gave users a fast way to gauge how closely a specific HAL matches the standard. Here's my proposition:

    Gold: The HAL uses the exact same prototypes as the language-specific API in the standard. This implies that code written for one gold-standard HAL can be copied/pasted and used with another gold-standard HAL of the same language without any errors (or if there are errors, those would be considered bugs worth reporting to the author... no one is perfect).
    Silver: The HAL uses the same function names and parameter names as the language-specific API in the standard. Return values, if applicable, also match the API standard. All parameters appear in the same order as the language-specific API in the standard. Types for parameters may differ.
    Bronze: The HAL drew inspiration from the standard but no guarantees are made about compatibility. Differences might include but are not limited to: package structure, object/function names, parameter types/names, parameter orders, etc.

    These "badges" can and should be self-administered. I don't think anyone wants to be in charge of reading through someone else's HAL and giving them the "gold stamp of approval." If you're a HAL author, figure out for yourself whether you have gold/silver/bronze compatibility and document your library as such - no need to ask permission.

    We're also going to want to version this project (semantic versioning but without the "patch" digit since this is only an API and can't have "bugs"). This will let people say "PropWare is a C++ HAL for the Parallax Propeller 2 with a Gold-standard rating on API v2.1."
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • DavidZemon wrote: »
    I'm having a hard time getting behind anything other than no types or JSON types in the LAAPI ("lap-ee"? "L-A-A-P-I"? "lae-pee"? life is hard...). I think anything more specific than that should be a decision based on the language and no attempt should be made to standardize that across different languages.
    Fair enough. I think we do need to differentiate between numbers and strings, so *some* kind of type information is needed, and I kind of think it would be useful to differentiate numbers between byte, word, and long. But I'm not hung up on it and if you prefer to just say "number" that's fine, and maybe more general for languages like javaScript that only have one type of number.
  • Okay, with that, I think I have enough information to draft a README for the new repository. I don't know if it will happen tonight, but if anyone else wants to express an opinion, please do so. Once I draft the first README, I'll upload it to GitHub under my own user account and add people as collaborators (this is something that needs to live in Parallax's team, but I don't have access to create new repos over there, nor do I have access to add users as collaborators).

    Once the repo is up, people can start submitting pull requests. I'll make sure the README has clear instructions and/or examples for how submissions should be formatted.

    I'm going to lock down the master branch so that all commits have to go through a PR, but I will hopefully be able to give permission to collaborators to approve PRs. What I want is that no one person should be changing the standard without agreement from some portion of the community. Maybe that's one other person. Maybe that's 10 other people. Maybe that's two specific people and one other person. No idea yet. I won't implement any limits at all right off the bat other than no committing directly to master.

    I have high hopes for this!
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • ALSO! Anyone have a name suggestion for this thing?

    PAPI for Propeller API...

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • DavidZemonDavidZemon Posts: 2,817
    edited 2019-03-06 - 21:21:52
    msrobots wrote: »
    ALSO! Anyone have a name suggestion for this thing?

    PAPI for Propeller API...

    Mike

    Love it :) PAPI. "pap-ee". Rolls off the tongue much better than lap-ee or lae-pee lol. Ambiguity with P1 could be a problem though.
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • "Papi" (pronounced PAH-pee) means "daddy" in Spanish. David Ortiz (a.k.a. "Big Papi") is a former Major League Baseball player who retired from the Boston Red Sox in 2016 at the age of 40.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • "Papi" (pronounced PAH-pee) means "daddy" in Spanish. David Ortiz (a.k.a. "Big Papi") is a former Major League Baseball player who retired from the Boston Red Sox in 2016 at the age of 40.

    -Phil

    Interesting trivia. I don't know what to do with this information though lol. Is it meant simply as random trivia, or are you trying to push for or against the name?
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • DavidZemon wrote:
    Is it meant simply as random trivia, or are you trying to push for or against the name?
    Neither, only to point out that the acronym might mean different things to different cultures. It's not a bad thing, like the Chevy Nova was. ("No va" in Spanish means "doesn't go." :smile: )

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • DavidZemon wrote:
    Is it meant simply as random trivia, or are you trying to push for or against the name?
    Neither, only to point out that the acronym might mean different things to different cultures. It's not a bad thing, like the Chevy Nova was. ("No va" in Spanish means "doesn't go." :smile: )

    -Phil

    Noted. Thanks :)
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • The Padjero did not sell well in Spain/Mexico either...

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • "Papi" (pronounced PAH-pee) means "daddy" in Spanish.
    -Phil

    It is synonymous to « grandpa » in French

Sign In or Register to comment.