New CAST instruction for Spin2

24567

Comments

  • Cluso99Cluso99 Posts: 14,964
    edited 2019-05-21 - 15:55:35
    Agreed for the second option where the numeric is specified.

    I like being able to start at non-zero even tho you’re really saying for example CAST n-x

    What is the pasm result? A table of addresses and you add ‘n’ to the base address? It’s sort of like using an XBYTE instruction with the skip bits all zero.

    What about JTABLE ?
        JTABLE n
          LOWER:  block4
          5: block5
          6: block6
          ...
          11: block11
          OTHER: block12
    

    Postedit

    Use JTABLE n-5 in the above example and code for 0... and forget LOWER:
    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)
  • EJMP, as in "enumerated jump"?
    garryj
  • tonyp12tonyp12 Posts: 1,943
    edited 2019-05-21 - 16:37:49
    Maybe get some ideas how C does it?

    All functions have to be of the same input/output, if you don't need that just use void void.
    C is strong type cast for your own safety, so to create a jump table takes some weird looking point type casting.

    Example 1
    pf[] is a static array of pointers to functions that take an INT as an argument and return void.
    void fna(INT);	// Example prototype of a function to be called
    
    // Declaration using typedef
    typedef void (* const PFV_I)(INT);
    static PFV_I pf[] = {fna, fnb, fnc, ..., fnz);
    
    // Direct declaration
    static void (* const pf[])(INT) = {fna, fnb, fnc, ..., fnz};
    
    // Example use
    INT a = 6;
    pf[jump_index](a);	// Calling method 1
    (*pf[jump_index])(a);	// Calling method 2
    
    
    https://barrgroup.com/Embedded-Systems/How-To/C-Function-Pointers
  • ceptimusceptimus Posts: 107
    edited 2019-05-21 - 16:48:09
    It's a bit like the ON X GOTO .... statement in some dialects of BASIC, so maybe you could use ONGOTO or ONGT for short.

    ongt x
    0: block_0
    1: block_1
    2: block_2
    3: block_3
    4: block_4
    5: block_5
    6: block_6
    >: block_other

  • A potentially cool name might be "gate." It's four letters, which many are leaning towards. Although it's more often a noun than a verb, "case" is also a noun. It could make the choices easy to talk about: For example, gate 3 moves the sprite to the right. Obviously, it's a play on airport terminal gates, which makes it memorable.
    gate x
      0: stayPut
      1: moveUp
      2: moveDown
      3: moveRight
      4: moveLeft
    
  • I strongly suggest the instruction be named either SELECT (BASIC) or SWITCH (C), CAST should be used for something like variable type casting, as that's the reserved usage in SQL.
  • Since it has essentially the same syntax as case and is just case with a different indexing mechanism, how about ICASE for index-case?
  • I like GOTO x followed by all the choices. It reminds me of the ancient BASIC days
    Finish the list with ELSE.
    Simple & Easy.
  • Roy ElthamRoy Eltham Posts: 2,615
    edited 2019-05-21 - 20:05:03
    I like PICK, SELECT, or CASETABLE, CAST has the wrong meaning. I also think it should be OTHER and absolutely not ? or >.
    I think it should require a number for each entry, but you can leave some out. The compiler can just fill in the unused table entries with the "other" entry.
    If there is no OTHER entry specified, then it can be implied as the next statement after the table.

    I agree with ersmith that making everything short cryptic symbols makes the code harder to read. Please don't go down that route.

    I also like the idea of the compiler just being able to do this with the regular CASE instruction. That's how C/C++ works when the compiler is decent, it produces jump table for switch/case constructs. I've even seen simple cases reduces to branchless code (but that gets pretty complex at the compiler level).
  • jmgjmg Posts: 13,535
    cgracey wrote: »
    Yes, I thought about making the compiler smart enough to compile this more-efficient method when circumstances allowed, but it will take some work and maybe new parsing approaches. I was thinking your compiler could probably handle that, easily.

    Surely that is easily the best solution, which is how other languages already do this ?
    The computer does the work, and you do not add more words, or more syntatic chaff, thus keeping the programmer's life simpler.

    Some compilers will give a choice of size or speed, and there is also a case form that a compiler arranges like
    case x
        0: block_0
        1: block_1
        2: block_2
        3: block_3
        4: block_4
        5: block_5
        6: block_6
        else: block_other
    
    Where each line compiles not to a compare then jump, but to a chain of DNJZ, or DJNF
    This only works if the numeric list is simply sequential, and starts at 1/0 - common to see this in Assembler code.
    VonSzarvas wrote: »
    I like the idea of casting a net.... But could "CAST" be confused as an operation to change type ?
    Yes, cast is already widely used elsewhere, where it means something else, so is best avoided
    cgracey wrote: »
    Bean wrote: »
    Chip,
    Unless "ON" has another meaning, I think "ON x" instead of "CAST x" would make more sense (at least to BASIC programmers).
    "ON" is pretty good, but it's an awfully small word, almost gets looked past:
    It's no smaller than 'if' :)

    In BASIC that looks like this
    on b1 gosub btn0,btn1, btn2, btn3
    
    cgracey wrote: »
    I kind of like everything being numbered, as well, because it's immediately clear. It's just a pain to rearrange..
    I'm not following the 'It's just a pain to rearrange' ?
    Code is always best to be able to add and remove lines, in an editor at will, and should tolerate lines added/commented without change of meaning.

    As an assist to compilers, FreeBasic takes this approach
    http://bourabai.kz/einf/freebasic/KeyPgSelectcase.html
    Here they use
    'If As Const is used, only Integer constants can be evaluated and the expression list supports single constants and enumerations only. "To" ranges are supported, but "Is" relational operators are not.
    With As Const, a jump table is created to contain the full range of integer Cases handled. This allows Select Case As Const to be faster than Select Case.
    However, the size of the range of values is limited, and the largest value in the range may be no higher than the smallest value + 4096."


    and Python has this approach possible
    if   x == 1: print('first')
    elif x == 2: print('second')
    elif x == 3: print('third')
    else:        print('did not place')
    

  • The "As Const" approach should work quite well: we could just add "CON" or "CONSTANT" after the "CASE" keyword to let the compiler know that it can use a jump table:
       CASE CONSTANT x
           0: block_0
           1: block_1
           other: block_other
    
    This is nice and simple for the programmer: it's just like "CASE", but the "CONSTANT" is a hint that the compiler can use to verify that all the case labels are constants. Fancier compilers can just ignore the "CONSTANT" and optimize to a jump table as they see fit.
  • I like the CASE CONSTANT x usage.

    Would be nice for ELSE: instead of, or an alternative to, OTHER:
    This is just a simplification of the language. I never understood why new languages had to invent new terms for existing operations eg SWITCH, SELECT, VOID, and so on.
    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)
  • Cluso99 wrote: »
    I like the CASE CONSTANT x usage.

    Would be nice for ELSE: instead of, or an alternative to, OTHER:
    This is just a simplification of the language. I never understood why new languages had to invent new terms for existing operations eg SWITCH, SELECT, VOID, and so on.

    I like ELSE better than OTHER, too. I'll get rid of OTHER and keep ELSE. We want a short name because it must be at the same indention level as the numbers.
  • PropGuy2 wrote: »
    I like GOTO x followed by all the choices. It reminds me of the ancient BASIC days
    Finish the list with ELSE.
    Simple & Easy.

    I like GOTO maybe best, too.
  • jmgjmg Posts: 13,535
    cgracey wrote: »
    PropGuy2 wrote: »
    I like GOTO x followed by all the choices. It reminds me of the ancient BASIC days
    Finish the list with ELSE.
    Simple & Easy.

    I like GOTO maybe best, too.

    ..but that adds a new keyword, and GOTO X is not actually 'going to X' at all, which is why BASIC uses ON X GOSUB/GOTO
    Seems best to keep existing keywords, and use the CONST modifier, if a compiler needs help to see a table can be used.
    Smarter compilers do not even need CONST, making things even simpler for the programmer.

    ELSE is widely understood, so is better than OTHER
  • jmg wrote: »
    cgracey wrote: »
    PropGuy2 wrote: »
    I like GOTO x followed by all the choices. It reminds me of the ancient BASIC days
    Finish the list with ELSE.
    Simple & Easy.

    I like GOTO maybe best, too.

    ..but that adds a new keyword, and GOTO X is not actually 'going to X' at all, which is why BASIC uses ON X GOSUB/GOTO
    Seems best to keep existing keywords, and use the CONST modifier, if a compiler needs help to see a table can be used.
    Smarter compilers do not even need CONST, making things even simpler for the programmer.

    ELSE is widely understood, so is better than OTHER

    Well, maybe CASEX, then. Some single word.
  • cgracey wrote: »
    jmg wrote: »
    cgracey wrote: »
    PropGuy2 wrote: »
    I like GOTO x followed by all the choices. It reminds me of the ancient BASIC days
    Finish the list with ELSE.
    Simple & Easy.

    I like GOTO maybe best, too.

    ..but that adds a new keyword, and GOTO X is not actually 'going to X' at all, which is why BASIC uses ON X GOSUB/GOTO
    Seems best to keep existing keywords, and use the CONST modifier, if a compiler needs help to see a table can be used.
    Smarter compilers do not even need CONST, making things even simpler for the programmer.

    ELSE is widely understood, so is better than OTHER

    Well, maybe CASEX, then. Some single word.

    Why a single word?

    Thinking about this some more I've come to the conclusion that the very best solution is to change the compiler to recognize when it can optimize CASE into a jump table. That way users don't have to learn two separate keywords (CASE and CASEX) and figure out when to use which one. It's better to do the hard work once (in the compiler) than to make every user do the optimization themselves every time they write a CASE statement.

    Second best, IMHO, is to add a modifier to the CASE statement (something like CONST) as a promise to the compiler that yes, it can optimize this case into a jump table, and throw an error if it can't.

    I think adding a new keyword is the worst solution, since it complicates the language without really adding any new functionality.

    If changing the compiler seems like a big task, could it not be postponed? After all this is just an optimization, it doesn't actually change what the language can do. In that case, why not just get something working (for now) and then go back and make it better later? People managed to get quite a lot of work done in Spin1 without this feature, after all :).

    Regards,
    Eric
  • jmgjmg Posts: 13,535
    edited 2019-05-21 - 23:16:08
    cgracey wrote: »
    Well, maybe CASEX, then. Some single word.
    That's tolerable, but still less than ideal to me, as it adds another keyword, and other language users will says "why does this Spin language have two case words ?"
    Best is to have compilers work like Verilog does, where it infers better structures, and reports what it has done. If that is too difficult, use the (optional) CONST as ersmith outlined
    ie ideally, programmers simply use CASE, and the compiler confirms it did see a table Case structure.
    A very smart compiler would see very short case lists are better done with a few DJNZ/DJNF than creating and loading a table, but larger case lists benefit from a table.
    I noticed FreeBASIC above puts a limit on the size of the table.

  • cgraceycgracey Posts: 11,132
    edited 2019-05-21 - 23:42:31
    I kind of like the idea of a special key word to invoke some hot rod version of CASE which requires certain attention on the programmer's part.
  • Isn't this is a special case to be decided by the programmer where a deterministic result is required ???

    So this
        CASEJMP x
          0:     label0
          1:     label1
          2..5:  label2
          6:     label6
          else:  labeln             
    
    will expand to something like this
        fge   x,#7                  ' max value
        shl   x,#2                  ' convert to long offset
        add   j,x
        nop
        nop
    j   jmp   table-0               ' indirect jump
    
    table long  label0
          long  label1
          long  label2
          long  label2
          long  label2
          long  label2
          long  label6
          long  label7
    

    CASEJMP, CASETBL, CASETABLE, JMPTABLE or something similar might work?
    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)
  • cgraceycgracey Posts: 11,132
    edited 2019-05-21 - 23:54:33
    Thinking about this, CASE optimization during compilation could be a whole sub-science of its own. We currently have a most-flexible implementation and a fastest implementation. Everything else would be in-between.
  • Cluso99 wrote: »
    Isn't this is a special case to be decided by the programmer where a deterministic result is required ???

    So this
        CASEJMP x
          0:     label0
          1:     label1
          2..5:  label2
          6:     label6
          else:  labeln             
    
    will expand to something like this
        fge   x,#7                  ' max value
        shl   x,#2                  ' convert to long offset
        add   j,x
        nop
        nop
    j   jmp   table-0               ' indirect jump
    
    table long  label0
          long  label1
          long  label2
          long  label2
          long  label2
          long  label2
          long  label6
          long  label7
    

    CASEJMP, CASETBL, CASETABLE, JMPTABLE or something similar might work?

    That is what the code looks like, all right. the implication of using words is that the entire CASE must fit within 64KB, which should never be a problem.
  • Please don't reuse else. else is part of the if/then/else stuff.
    I also don't understand this desire to shorten everything. There is no need for it.
    Use DEFAULT for the other case, that will match what C/C++ does with switch/case stuff, and not be reusing something that already exists in the language (as far as I know).
    also, why not CASE JUMP or CASE CONSTANT? it's a special case of CASE, why not have it be a keyword following it instead of mashing it up like an ASM instruction? This is not ASM.
  • "goto" is interesting. I still like "jump". But, what about "branch"?
    Prop Info and Apps: http://www.rayslogic.com/
  • jmgjmg Posts: 13,535
    edited 2019-05-22 - 01:44:41
    Roy Eltham wrote: »
    Please don't reuse else. else is part of the if/then/else stuff..
    That does not stop using the same word.
    ELSE is in common use, in many languages, outside of if statements alone.
    Roy Eltham wrote: »
    also, why not CASE JUMP or CASE CONSTANT? it's a special case of CASE, why not have it be a keyword following it instead of mashing it up like an ASM instruction? This is not ASM.

    I'm fine with either of those, but a better compiler would use a TABLE depending where it was told to choose speed or size, and not need CONSTANT
    In the code above, less than somewhere about 6 case choices, would be smaller and faster via DJNF opcode, assuming the reach is ok, whilst above that, table, is larger but faster, for later choices,

  • jmg wrote: »
    Roy Eltham wrote: »
    Please don't reuse else. else is part of the if/then/else stuff..
    That does not stop using the same word.
    ELSE is in common use, in many languages, outside of if statements alone.
    Roy Eltham wrote: »
    also, why not CASE JUMP or CASE CONSTANT? it's a special case of CASE, why not have it be a keyword following it instead of mashing it up like an ASM instruction? This is not ASM.

    I'm fine with either of those, but a better compiler would use a TABLE depending where it was told to choose speed or size, and not need CONSTANT
    In the code above, less than somewhere about 6 case choices, would be smaller and faster via DJNF opcode, assuming the reach is ok, whilst above that, table, is larger but faster, for later choices,

    To inform the compiler the optional keyword following CASE could be a member of a set like:

    SMALL - uses the smallest memory footprint, regardless of performance
    FAST - uses fastest method regardless of memory size
    TABLE - directs the use of a table, even if other methods might be smaller or faster.

    The absence of the optional keyword could then employ a heuristic to determine which structure to use in the situation. Some fairly simple analysis should identify which method is best for the specific code being compiled.

    This gives beginners the opportunity to ignore the compiler directive keywords until they run across a case (pun unintended) where they need them.

  • jmgjmg Posts: 13,535
    AJL wrote: »
    jmg wrote: »
    Roy Eltham wrote: »
    Please don't reuse else. else is part of the if/then/else stuff..
    That does not stop using the same word.
    ELSE is in common use, in many languages, outside of if statements alone.
    Roy Eltham wrote: »
    also, why not CASE JUMP or CASE CONSTANT? it's a special case of CASE, why not have it be a keyword following it instead of mashing it up like an ASM instruction? This is not ASM.

    I'm fine with either of those, but a better compiler would use a TABLE depending where it was told to choose speed or size, and not need CONSTANT
    In the code above, less than somewhere about 6 case choices, would be smaller and faster via DJNF opcode, assuming the reach is ok, whilst above that, table, is larger but faster, for later choices,

    To inform the compiler the optional keyword following CASE could be a member of a set like:

    SMALL - uses the smallest memory footprint, regardless of performance
    FAST - uses fastest method regardless of memory size
    TABLE - directs the use of a table, even if other methods might be smaller or faster.

    The absence of the optional keyword could then employ a heuristic to determine which structure to use in the situation. Some fairly simple analysis should identify which method is best for the specific code being compiled.

    This gives beginners the opportunity to ignore the compiler directive keywords until they run across a case (pun unintended) where they need them.

    Yes, that's quite a good idea.
    I can think of one case where you might want a TABLE, even tho it may be slower in some paths, and that would be for a known & fixed delay path choice.
  • gcracey wrote:
    ">" is supposed to mean "out-of-bounds" or "greater-than".

    I like other better. But cast? Not so much. How about index?

    But why do we need a separate keyword to begin with? Can't the case parsing decide between a high-maintenance case situation and something more efficient? This is a problem for the compiler, not for the Spin language, per se.

    IOW make your job complicated to keep the language simple -- please.

    -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
  • ACTION x
    
       0:     label0
          1:     label1
          2..5:  label2
          6:     label6
          else:  labeln
    
    
    Melbourne, Australia
  • gcracey wrote:
    ">" is supposed to mean "out-of-bounds" or "greater-than".

    I like other better. But cast? Not so much. How about index?

    But why do we need a separate keyword to begin with? Can't the case parsing decide between a high-maintenance case situation and something more efficient? This is a problem for the compiler, not for the Spin language, per se.

    IOW make your job complicated to keep the language simple -- please.

    -Phil

    The thing is, this is the highest-performance CASE possible. There are some strict requirements about how it needs to be set up by the user. It's possible that the user could miss some requirement and end up with a normal, much slower CASE. Therefore, I think it's appropriate to give this a separate name, to be sure that its requirements are met.
Sign In or Register to comment.