rokucommunity / rokucommunity/brighterscript

runtime enum lookup

Open
#597 4 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
208
Forks
68
Avg merge
8h 39m
Merged PRs (30d)
39

Description

BrighterScript should support looking up enum values at runtime by their key. For performance reasons, we should generate two different functions for enums:

  • GetValue(key) - will support looking up an enum value by its key. This will be implemented as a series of if statements to improve performance (no need to generate a full AA just to throw most of it away)
  • GetAA() - will support getting the enum as an AA where the keys are the enum names, and the values are the enum values.

At compile-time, we'll look at how the enum is used to determine how to transpile them.

  • Direct references like Enums.Direction.Up will continue to be transpiled inline to their literal values.
  • indexed access like Enums.Direction[someString] will use the GetValue(key) pattern for performance reasons
  • direct enum references like print Enums.Direction will use the GetAA() pattern.

Here's some example code:

Source:

namespace Enums
    enum Direction
         up = 1
         down = 2
    end enum
end namespace

sub main()
    'existing functionality
    print Enums.Direction.Up

    'new proposed functionality: get  enum value
    print Enums.Direction["down"]

    'new proposed functionality: get enum as AA
    enumAA = Enums.Direction
    for each key in enumAA.keys()
        print enumAA[key]
    end for
end sub

Transpiled

sub main()
    print 1

    'new proposed functionality: get  enum value
    print = Enums_Direction_GetValue("down")
    
    'new proposed functionality: get enum as AA
    enumAA = Enums_Direction_GetAA()
    for each key in enumAA.keys()
        print enumAA[key]
    end for
end sub

function Enums_Direction_GetValue(key as string)
    'enum names are case insensitive
    key = LCase(key)
    if key = "up"
        return 1
    else if key = "down"
        return 2
    else
        return invalid
    end if
end function

function Enums_Direction_GetAA()
    return {
        up: 1
        down: 2
    }
end function

Here's some untested plugin code for generating the GetValue(key) pattern:

afterFileParse(file: BscFile) {
    if (isBrsFile(file)) {
        file.ast.walk(createVisitor({
            EnumStatement: (stmt) => {
                let ifStatements = [...stmt.getMemberValueMap()].map(([key, value], index)=>{
                    const ifKeyword = index === 0 ? 'if' : 'elseif';
                    return `${ifKeyword} key = ${key} then\n return ${value}`;
                }).join('\n') + '\nendif';

                //create a function for this enum that will return the enum value for a given key. For example, an enum named `Direction`, this would produce
                //`function GetDirectionValue(key)`.
                const enumValueFactory = Parser.parse(`
                    function ${stmt.name.toString()}_GetValue(key as string)
                        ${ifStatements}
                    end function
            `).ast.statements[0];
                file.ast.statements.push(
                    enumValueFactory
                );
            }
        }), { walkMode: WalkMode.visitStatements });
    }
}

Here's an untested plugin for the GetAA() pattern.

afterFileParse(file: BscFile) {
    if (isBrsFile(file)) {
        file.ast.walk(createVisitor({
            EnumStatement: (stmt) => {
                //create a function for this enum that will return its values. For example, an enum named `Direction`, this would produce
                //a function called `DirectionValues()` that returns an AA with the enum values
                const enumValueFactory = Parser.parse(`
                    function ${stmt.name.toString()}_GetAA()
                        return {
                            ${[...stmt.getMemberValueMap()].map(member => `${member[0]}: ${member[1]}`).join('\n')}
                        }
                    end function
                `).ast.statements[0];
                file.ast.statements.push(
                    enumValueFactory
                );
            }
        }), { walkMode: WalkMode.visitStatements });
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the compiler's EnumStatement handling and the afterFileParse examples, then inspect getMemberValueMap and Parser.parse usage. Compare the requested direct, indexed, and whole-enum access paths. Done means runtime enum lookup returns values case-insensitively, whole-enum access returns an AA, and existing direct references remain inline.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.