Giter Site home page Giter Site logo

brighterscript's People

Contributors

agohof avatar arturocuya avatar bartvandenende-wm avatar cewert avatar chrisdp avatar christian-holbrook avatar dependabot[bot] avatar elliot-nelson avatar elsassph avatar enthooz avatar fumer-fubotv avatar georgejecook avatar ibicha avatar iobject avatar jfrux avatar josephjunker avatar justinmbullard avatar kwottrich avatar luis-soares-sky avatar markwpearce avatar mikealmartinez avatar milapnaik avatar philanderson888 avatar slheavner avatar timalacey avatar trevorsundberg avatar triwav avatar twitchbronbron avatar xgouchet avatar zeed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brighterscript's Issues

require override keyword for overriding class methods

I'm already starting to need this issue in my bs code.. would be lovely if, given a class

class BaseClass

public function load()

that the extended class

class SpecificThingLoader
public function load()

will throw a compiler error.

The syntax in this case should be

override public function load()

I'm not suggesting we support super classes at this point; though I may in future; but truth be told, I've only ever had to swizzle an aa for a superclass access less than a handful of times.

support interface for aas

Similar to class, we should allow interface. this will allow us to get to a goal where the ide will have increasing information about types.

interface would produce nothing in the brs code - the benefit of the type declaration would be entirely for the ide's symbol and definition resolution and the compiler.

example

interface styleInfo
  selectedColor: string
  color: string
  fontSize : integer
end struct

public function someMethod(buttonStyle: StyleInfo)
  button.applyStyle(styleInfo)
end function

output is






public function someMethod(buttonStyle: StyleInfo)
  button.applyStyle(buttonStyle)
end function

the interface would simply vanish at runtime; merely providing the ide with more type info. This does of course require that we have more advanced typing, which i would dearly love to see, whereby we can have as default values (object|integer|dynamic) as well as new specific types for our classes and interface (StyleInfo|MyButton|UserInfo|FancyButton), whereby the types here are the class or node names.

additional language support functions: BS_LINENUM(), BS_FILE(), BS_FUNCTION()

wouldn't it be great if we could drop these into the code at any time, like macros, so that they could be resolved at compile time. These are super handy for debugging, and currently require the use of third party tools.

Suggestion

print "unknown error occurred " ; BS_FILE() ; "." BS_FUNCTION() ; BS_LINENUM()

Would compile to
print "unknown error occurred pkg:/path/ToFile.brs.LoadStuff(23)"

DIM statement is not supported

For the following example:

sub doSomething()
    Dim c[5, 4, 6] 
    For x = 1 To 5
        For y = 1 To 4
            For z = 1 To 6
                c[x, y, z] = k
                k = k + 1
            End for
        End for
    End for 
end sub 

Taken from Roku documentation found: here

the Dim statement is flagged as error 1081 ("Found enexpected token 'Dim'") and appears to be unsupported.

Incorrectly reporting errors

Operating System: Fedora 30
VS Code: 1.44.0
BRS Extension: 2.1.2

I am getting red squiggle lines under code which is actually correct. It was on a huge non-SG screensaver main.brs, but I can reproduce it at will with the following steps.
$ mkdir test
$ cd test
$ code .

Open a new Untitled file, and then type or paste the following code:

Function RunScreenSaver( params As Object ) As Object
     main()
End Function

sub main()
    print "Entering main()..."
    m.screen  = CreateObject("roScreen")                    ' Required object
    m.port    = CreateObject("roMessagePort")               ' Required object
    di        = CreateObject("roDeviceInfo")                ' For resolution info
    timeStamp = CreateObject("roDateTime")                  ' For elapsed time
    i% = 1

    i% = i% << 3
    i% = i% >> 3

    for j = 1 to 10
        print j
    next j

    for k = 1 to 10
        print k
    end for

end sub

All should look well, until you hit <CTRL-S> and save as main.brs. After writing to disk, the red marks appear, as shown in the attached screenshot below.

There was a red squiggle under the "j" in "next j" but I upgraded the version of VS Code and the extension this morning and I can no longer reproduce that.

My screensaver compiles and runs fine even with the squigle marks.

Screenshot from 2020-04-12 09-56-33

Warns of file not existing for common:/ files

<script type="text/brightscript" uri="common:/LibCore/v30/bslCore.brs" /> warns about the file not existing. Could either search for anything beginning with common:/ and not search for it or make a whilelist of accepted files. Think there are only 2 or 3 maybe.

thoughts on compiling bs, that interops with _compiled_ bs

given TodoVM.bs

class TodoVM extends BaseViewModel

where BaseViewModel is a library that I import in my project with compiled sources (i.e. BaseViewModel.brs), how does the compiler know the extend is valid?

I have this currently in my project, so I'm distributing both compiled and uncompiled sources.
I'm also thinking of adding options to turn the class BaseViewModel not found error into a warning; but it got me thinking...

is there some lightweight metadata we can bundle in comments at the bottom of a file, or something similar to d.ts file, which the compiler can read, to not lose important information when encountering compiled sources.

Optional Chaining

When looking for a property value that's deep in a tree-like structure, one often has to check whether intermediate nodes exist:

if user.address AND user.address.street then
  street = user.address.street
end if

Also, many API return either an object or Invalid, and one may want to extract a property from the result only when it is not Invalid:

fooInput = m.top.findNode('fooIinput')

if Invalid <> fooInput then
  fooValue = fooInput.value
end if

The Optional Chaining Operator allows a developer to handle many of those cases without repeating themselves and/or assigning intermediate results in temporary variables:

street = user.address?.street
fooValue = m.top.findNode('fooInput')?.value

My examples above are just tweaks to the one on this repo: https://github.com/tc39/proposal-optional-chaining

Attribute operator causes parse error

This is valid BrightScript syntax (see this BrightScript documentation page for info):

xml = CreateObject("roXMLElement") 
xml.parse("<?xml version=""1.0"" encoding=""UTF-8""?><person name=""bob"" age=""12""></person>")
print "xml age: "
print xml@age 'notice the @ symbol being used to read the attribute from the xml element

prints out

xml age: 
12

However, the brighterscript cli shows a parse error.

Conditional compilation should allow operators

Preprocessor statements such as this:

#if not production
   ? "Debug Version"
#else
   ? "Production Version"
#end if

Give a 1091 error ("#if conditionals can only be 'true', 'false', or other #const names"). This doesn't seem to be the case for vanilla BrightScript as can be seen in the example in the Roku documentation:

Conditional Compilation - Roku Documentation

Unfortunately the Roku docs don't expand on which operators are permitted. It's probably relatively safe to assume that the logical operators (AND, OR, NOT) are OK, but what about others? The code shown above works fine on a Roku device.

support continue statement

super useful statement, get's rid of need for huge if statements
can easily be implemented under the hood by injecting gotos

example code

for i = 0 to 10 
  item = items[i]
  if item.isLocked
    continue
  end if

  doSomeStuffwithItem(item)
end for

will produce code:

for i = 0 to 10 
  item = items[i]
  if item.isLocked
    goto namespace_class_method_continue1
  end if

    doSomeStuffwithItem(item)

  namespace_class_method_continue1:
end for

note, I suggest we namespace the continue label with namespace_class_method_continue_index, as we could have multiple continues in one method, or even one loop.

it might be we just namespace on per file indexes though (i.e. take filename, and each continue that appears in the file has an index that increments each time a continue is encountered)

Allow a node to require extend

So just learned that a node doesn't have to extend from another node type as it appears to fall back to using Group by default. This should not be reported as an error like it currently is Component must have an extends attribute.brs(1007)

Error detecting compile issue in if block

The latest version of brighterscript was failing to detect the following as a compile issue:

if key = "back" AND then
end if

Here are some other examples that it also failed to detect:

if key = "back" OR then
end if
if key = "back" MOD then
end if

Node or AA based Class Support

Is there anyway we could do classes ether as AA out put or as Node output. I say this because internally we avoid AA's as much as possible.

this is a good suggestion - so something like NodeClass? whereby

  • automatcially creates a className.xml,
  • imports the declaring brs file into className.xml
  • the public methods become <function> interface entries in className.xml
  • public fields become <field> entries on className.xml

There's a lot in this idea - I think you should raise it as a separate issue - as it's a hugely useful; but also huge feature; but (imho) way beyond the scope of pobo (i.e. aa) classes

The above was a response from @georgejecook

Originally posted by @chrisdp in #1 (comment)

Import specification

Justification

It can get very difficult sometimes to keep track of what files depend on one another. Many other programming languages have the concept of imports, and this specification brings that concept to brighterscript.

Syntax

import "pkg:/source/lib.brs"
import "../lib.brs"
import "lib.brs"

Output

For source scope (i.e. pkg:/source and everything below), an import statement will cause that file to be included in pkg:/source folder during packaging.

For component scope, any component that references a script that has imports, those imports will be added to the component's script imports. For example, consider these source files:

  • src/components/MyComponent.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <component name="MyComponent" extends="Scene">
     <script type="text/brightscript" uri="MyComponent.brs" />
    </component>
  • src/components/MyComponent.brs
    import "pkg:/source/lib.brs"
    function DoSomething()
    end function

This will result in the output files as such:

  • pkg:/components/MyComponent.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <component name="MyComponent" extends="Scene">
     <script type="text/brightscript" uri="MyComponent.brs" />
     <script type="text/brightscript" uri="pkg:/source/lib.brs" />
    </component>
  • pkg:/components/MyComponent.brs
    function DoSomething()
    end function

error BS1000: Unexpected character '@'

for each outline in feedXml.body.outline
     ' ...
      display = ValidStr(outline@display) ' throws error BS1000: Unexpected character '@'
     ' ...
end for

Any tips on how to re-write this?

Flag unused script imports

In case a XML Scenegraph component includes a script file and all the functions in that script file, are not used in the object - flag it.

This can help reduce unnecessary bloat.

Type keyword that returns BrighterScript object type

would be great to have a type keyword that could return the brightscript or brighterscript type of an object. So if it's a brighterscript class, you'll get className, if it's a node/primitive, you'll get the default type

absolutely off the charts insane static type checking on everything

we could perhaps/maybe/theoretically create a shadow project, in typescript, with types that match the brightscript project's types, and use that to ascertain all of our type/scope errors..

point being, use typescripts type inference as a proxy, rather than having to write it all for brighterscript.

optionals, use question mark at the end of a var name to support assignment to invalid

Similar to Type Declaration Characters such as $ (String), % (Integer), ! (Float), # (Double), & (LongInteger), which don't allow assignments of invalid, we could make the language null-safe by never allowing assignments of invalid unless the var name ends with ? by creating a runtime error.

Like in Swift, this value could be an associative array with two possible values in it, none or some, with the associated value. (Swift does that with an Enum). To assign an optional to a non-optional, an unwrapping function is needed which releases the some value or provides an alternative if none is encountered.

Sourcemap support

When generating the brightscript output, brighterscript should also produce sourcemaps so that debuggers can map output line/column numbers to source line/column numbers.

Ternary operator

myValue = (false) ? "value1" : "value2"

print myValue 
' Output: value2

support switch statements

switch something
   case somethingElse1:
            ' ...
   case somethingElse2:
            ' ...
   case somethingElse3:
            ' ...
   default:
            ' ...
end switch

should transpile to:

if something = somethingElse1 then
    ' ...
else if  something = somethingElse2 then
    ' ...
else if  something = somethingElse3 then
    ' ...
else
   ' ...
end if

may because of the if else, the break statement is implied, otherwise it might be transpiled with goto statements to support fallthrough.

if something = somethingElse1 then
   goto somethingElse1Label
else if ...
somethingElse1Label:
   '...

Runtime type checking for function parameters

we could theoretically have code like

function myFoo(arg1 as node, arg2 as string, arg3 as Group, arg4 as myNameSpace.NetModule

and the transpiler/thingy could inject a line of code below the function definition to ensure the runtime type.

support await keyword

I propose that we support async/await semantics in brighterscript.

example:

      private async function login()
        m.account = await m.getAccount(m.nameInput.text, m.passwordInput.text
        if m.account
          m.username.label.text = m.account.name
        else
          m.username.label.text = "ERROR"
        end if
     end function

    private async function getAccount(name as string, password as string)
      token = await m.getToken(name, password)
      user = await m.getUserAccount(token)
      return user <> invalid ? user.account : invalid
    end function

    private async function getToken(name as string, password as string)
      'returns a promise, as per roku-promise (i.e a creates a task with an out field)
      'e.g.
      task = createObject("roSGNode", "UserTask")
      task.command = "getToken"
      task.name = name
      task.password = password
      task.control = "RUN"
      return task
    end function

    private async function getUserAccount(token as string)
      'returns a promise, as per roku-promise (i.e a task with an out field)
      task = createObject("roSGNOde", "UserTask")
      task.command = "getAccount"
      task.token = token
      task.control = "RUN"
      return task
    end function

add mechanism to replace node.callfunc("foo", with node.foo syntax

It'd be wonderful to not have to use callfunc anymore

given a node with function foo, I want to be able to do
node.foo, instead of node.callFunc("foo"

I also want to be able to call it like a regular function without having to pass a single args param, i.e.

node.foo(title, video, someOtherThing)

as opposed to node.callFunc("foo", {title:title, video:video, someOtherThing"..etc)

an idea to achieve this, without having to need full-bulletproof type checking implemented is something like this

  1. all .bs defined functions that map to an xml file's node's public interface functions result in the creation of a new function (e.g. foo_public) and the xml interface's definition will use that for function calls - the code for that destructures args to the fieldnames in the real method signature, and invokes that method
  2. all callfuncs are replaced with BS_callFunc(node, arg1, arg2, arg3)
  3. that will bundle the args up and pass them into node.callfunc

Files referenced with createChild() are triggering warning BS1013

Forgive me if this is too general of an issue and may not be true in all situations but this is just what I'm seeing in this particular codebase I'm working on. (NOTE: I'm very very new to Roku dev so forgive me if any of this looks silly haha)

' Constants.brs
' ...
    sub Init()
        ' ...
        m.top.something = "something"
        ' ...
    end sub
' ...
' SomeFile.brs
' ...
    sub Init()
        ' ...
        m.c = m.top.createChild("Constants")
        ' ...
    end sub
' ...

Only parse XML files found within the components folder

XML files found outside of the pkg:/components/ folder should be excluded from parsing/validating.

image

Roku will throw exceptions for any non-component-structured xml file in the components folder.

<?xml version="1.0" encoding="utf-8" ?>
<note>
	<to>Tove</to>
	<from>Jani</from>
	<heading>Reminder</heading>
	<body>Don't forget me this weekend!  </body>
</note>
error:
=================================================================
Found 9 parse errors in XML file test.xml
--- Line 2: No top level <component> element found
--- Line 3: No top level <component> element found
--- Line 3: Unexpected data found in file (first 10 characters are "Tove")
--- Line 4: No top level <component> element found
--- Line 4: Unexpected data found in file (first 10 characters are "Jani")
--- Line 5: No top level <component> element found
--- Line 5: Unexpected data found in file (first 10 characters are "Reminder")
--- Line 6: No top level <component> element found
--- Line 6: Unexpected data found in file (first 10 characters are "Don't forg")

Truthy and Falsy Support

if (true) then print "Truthy!"

if ({}) then print "Truthy!"

if ([]) then print "Truthy!"

if ("some string") then print "Truthy!"

if (3.14) then print "Truthy!"

if (new Date()) then print "Truthy!"
if (false) print  "Falsy."

if (muUndefinedVar) print  "Falsy."

if (Invalid) print  "Falsy."

if (0) print  "Falsy."

if ("") print  "Falsy."

Namespace specification

This is a proposal for namespaces.

Syntax

'simple
namespace App
    function GetSettings()

    end function
end namespace

'multi-part
namespace App.UI.Screens
    function MainScreen()
    end function
end namespace

'nested
namespace App
    namespace Util
        namespace Functions
            function GetSomething()
            end function
        end namespace
    end namespace
end namespace

Output

function App_GetSettings()
end function

function App_UI_Screens_MainScreen()
end function

function App_Util_Functions_GetSomething()
end function

#Usage

BrighterScript

sub main()
    App.GetSettings()
    App.UI.Screens.MainScreen()
    App.Util.Functions.GetSomething()
end sub

BrightScript

sub main()
    App_GetSettings()
    App_UI_Screens_MainScreen()
    App_Util_Functions_GetSomething()
end sub

Class specification

This is a proposal for classes. Here is the brighterscript syntax:

Syntax

class VideoPlayer
    'public constructor
    public sub New(url as string)
        m.url = url
    end sub

    'properties
    public url as string
    private isPlaying as boolean = false

    'public method
    public play() 
        m.isPlaying = true
        m.updateVideoStatus()
    end function

    'private method
    private updateVideoStatus()
        'do something private here
    end sub

end class

Output

function VideoPlayer(url as string)
    instance = {
        url: nothing,
        'underscore denotes private
        _isPlaying: nothing,
        play: VideoPlayer_play,
        _updateVideoStatus: VideoPlayer__updateVideoStatus
    }
    
    'constructor body
    instance.firstName = firstName
    instance.lastName = lastName
    instance.fullName = firstName + " " + lastName
    
    return instance
end function

function VideoPlayer_play()
    m.isPlaying = true
    m._updateVideoStatus()
end function

'double underscore (one for namespacing, the other for indicating private

function VideoPlayer__updateVideoStatus()
    'do something private here
end sub

Usage

BrighterScript

'usage
sub main()
    player = new VideoPlayer("some_url")
    player.play()
end sub

BrightScript

sub main()
    player = VideoPlayer("some_url")
    player.play()
end sub

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.