Giter Site home page Giter Site logo

basic-cli's People

Contributors

agu-z avatar anton-4 avatar ayazhafiz avatar bhansconnect avatar brzezinskip avatar faldor20 avatar imclerran avatar isaacvando avatar kilianvounckx avatar lindskogen avatar lukewilliamboswell avatar prathump avatar rtfeldman avatar smores56 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

basic-cli's Issues

Missing Utc module "FILE NOT FOUND"

Trying to access the Utc module that appears to be part of the basic-cli

app "myapp"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.1/97mY3sUwo433-pcnEQUlMhn-sWiIf_J9bPhcAFZoqY4.tar.br" }
    imports [
        pf.Utc,
    ...
$ roc dev
Downloading https://github.com/roc-lang/basic-cli/releases/download/0.3.1/97mY3sUwo433-pcnEQUlMhn-sWiIf_J9bPhcAFZoqY4.tar.br
    into <user>/.cache/roc/packages

── FILE NOT FOUND ──────────────────────────────────────────────── UNKNOWN.roc ─

I am looking for this file, but it's not there:

    <user>/.cache/roc/packages/github.com/roc-lang/basic-cli/releases/download/0.3.1/97mY3sUwo433-pcnEQUlMhn-sWiIf_J9bPhcAFZoqY4/Utc.roc

Is the file supposed to be there? Maybe there is a typo in the file
name?

When I inspect that directory, indeed there is no Utc.roc file. It's not clear to me whether this is intended to be a public module, but the functions inside looked useful.

Change `main` type to `Task {} U32`

Currently, we have a Task for exiting the process immediately. This is also currently the only way to exit with a nonzero exit code, so if you want to translate errors into nonzero exit codes, you have to explicitly run that task.

There would be a couple of advantages to having main be Task {} U32:

  1. When you want to have a nonzero exit code, you can just translate your particular error into the appropriate U32. You don't have to run a separate task.
  2. Control flow gets more consistent: nothing does an early exit, everything just translates error types as normal. This should make testing subsections of the program easier in the future, because instead of simulating an exit, you can just check whether the task succeeded or failed.
  3. You get more information out of your Task types. For example, if a Task has an error type of *, you know it's not doing an early exit.
  4. In a future where we have platform-agnostic effects, code wouldn't get written which relied on the "exit" effect. That in turn would make it easier to share, and/or would simplify ecosystem dependencies.

The reason to have it be Task {} U32 instead of Task U32 [] is because:

  • It makes the learning curve more gradual. Hello World is still main = Stdout.line "Hello, World!" - you don't need to learn about error handling right away; that can come later.
  • It means you don't need to go out of your way to translate successful operations that produce {} (e.g. Stdout.line, File.write, etc.) into 0

improve docs

A great way to make an impactful contribution is to read through the docs and try to improve them. Feel free to select me to review your PR.

Cannot run program using basic-cli platform on pop os

I was going through the tutorial and got to creating an application https://www.roc-lang.org/tutorial#building-an-application. I copied and pasted the code and I get this error

An internal compiler expectation was broken.
This is definitely a compiler bug.
Please file an issue here: https://github.com/roc-lang/roc/issues/new/choose
thread 'main' panicked at 'No such file or directory (os error 2)', crates/linker/src/metadata.rs:58:71
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Here's my system information:
OS: Pop!_OS 22.04 LTS
Roc Version: roc_nightly-linux_x86_64-2022-11-27-468be47.tar.gz

http-get example crashes on compilation

Hi all, with the latest nightly built from source on Ubuntu 20 (WSL), running this example hangs the Rust compiler:

$ roc http-get.roc
thread 'main' panicked at 'assertion failed: !self.not_reference_counted.contains(symbol)', crates/compiler/mono/src/inc_dec.rs:98:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
^C

It does this for : packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br" }

as well as for this version: packages { pf: "../src/main.roc" }

Any idea what could be wrong here? Thanks!

Example time.roc doesn't display duration in Stdout.line

   duration = Utc.deltaAsNanos start finish |> Num.toStr

    Stdout.line "Completed in \(duration)ns"

start and finish can be shown with dbg, and duration also when removing |> Num.toStr
Num.toStr probably doesn't work on U128 (which is the type of duration), so nothing (but also no error) is displayed.

Command.Error is not exposed

We should have a compiler error for the situation where an exposed type includes a named type that's not exposed, but we don't yet. 😅

`basic-cli` is using an outdated version of `roc-std`

The lock file has been keeping basic-cli using a version of roc-std from mid January. As such, it will break if passed a seamless slice.

I think it may be worth removing the lock file from basic-cli so that we always pull in the latest roc-std when publishing it. Otherwise, maybe we should add a cargo update to the publishing process? Fundamentally we want this to stay in sync.

Dir.list function is crashing on linux

ubuntu linux, Dir.list is crashing with error
Dir.list...
munmap_chunk(): invalid pointer
roc nightly pre-release, build from commit 1aa928b on Sa 19 Nov 2022 09:32:56 UTC

reduce produced binary size

Roc apps built with basic-cli can have a size in excess of 100MB, this should be investigated and reduced.

type mismatch `connection between types must use a named type variable, not a *`

app "helloWorld"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" }
    imports [pf.Task.{ Task }, pf.Stdout]
    provides [main] to pf


hello : Task {} *
hello =
    Stdout.line "Hello Alice"

hi : Task {} *
hi =
    Stdout.line "Hey Bob"

main =
    _ <- Task.await hello

    hi

This yields:

❯ ./target/release/roc check examples/helloWorld.roc 

── TYPE MISMATCH ───────────────────────────────────── examples/helloWorld.roc ─

This 2nd argument to await has an unexpected type:

16│>      _ <- Task.await hello
17│>
18│>      hi

The argument is an anonymous function of type:

    {} -> Task {} *

But await needs its 2nd argument to be:

    {} -> Task {} *

Tip: Any connection between types must use a named type variable, not
a *!

────────────────────────────────────────────────────────────────────────────────

1 error and 0 warnings found in 51 ms.

I sort of get why this happens but I believe this should work, unlike #1931 we're literally restating the type of Stdout.line.

Context: #2052

Request to specific API causes NetworkError on WSL

I have this minimal reproducing example with a basic GET to a specific API:

app "http-network-error"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" }
    imports [pf.Http, pf.Task.{ Task }, pf.Stdout]
    provides [main] to pf

main : Task {} I32
main =
    request = {
        method: Get,
        headers: [],
        url: "https://api-extern.systembolaget.se/site/V2/Search/Site",
        body: Http.emptyBody,
        timeout: NoTimeout,
    }

    output <- Http.send request
        |> Task.onErr \err -> err 
            |> Http.errorToString 
            |> Task.ok
        |> Task.await

    Stdout.line output

On Apple silicon it works as expected (no credentials passed, hence 401):

~/S/p/roc ❯❯❯ uname -a
Darwin Richards-MacBook-Pro.local 23.0.0 Darwin Kernel Version 23.0.0: Fri Sep 15 14:43:05 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T6020 arm64
~/S/p/roc ❯❯❯ roc --version
roc nightly pre-release, built from commit e65f14fa496 on Sat Dec  2 09:15:51 UTC 2023


~/S/p/roc ❯❯❯ roc dev http-network-error.roc
Request failed with status 401

But on my Windows machine running WSL2 it returns NetworkError:

~/s/b/examples ❯❯❯ uname -a
Linux DESKTOP-4Q7NKTK 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
~/s/b/examples ❯❯❯ roc --version
roc nightly pre-release, built from commit e65f14f on Sa 02 Dez 2023 09:07:00 UTC


~/s/b/examples ❯❯❯ roc dev http-network-error.roc
Network error

However, querying other API:s such as https://catfact.ninja/fact work well on WSL2 with the same example code. Also, cloning this repo and importing the platform as packages { pf: "../src/main.roc" } works with the troublesome API.

Any idea of why, or any suggestions on how to further debug?

Arena allocation

There should be a Task.withArenaAlloc function that initializes an arena allocator before running the task.

A while ago, I tried implementing it as an example: roc-lang/roc#4943

In this implementation, the function takes (U8 -> Task a err) instead of Task a err to prevent allocations from being performed in the task expression before the arena allocator is initialized. A cleaner and more reliable solution would be for the function's type to be a, (a -> Task b err) -> Task b err.

There could also be a similar function of type a, (a -> b) -> b for when no tasks need to be run.

Bad exit code

Currently, we aren't correctly setting the exit code and it can be random.

In lib.rs, we have pub extern "C" fn rust_main(). It does not return an exit code.
Then in host.c we have int main() { return (int)rust_main(); }. We take the void return value and cast it to an int.

we should either change that to:

int main() {
    rust_main();
    return 0;
}

Or we should change rust_main to return an int.

Support appending to file

I'm not sure if we should add an argument like [CleanWrite, Append] to the write functions or create separate append functions. We should take a quick look how other languages do this.

thread 'main' panicked at 'no entry found for key' - when using record update syntax

OS: macOS 13.2.1
(I know there's a warning that this is not officially supported, so please feel free to ignore this whole issue if this is the root cause)

Roc Version: roc nightly pre-release, built from commit 512b936 on Sun Mar 12 09:08:15 UTC 2023

Note: I'm not sure if this is a platform error, or a roc-lang error.

I'm able to successfully run the http-get example, code. However, when I change it to use the record update syntax, it fails to run with:

thread 'main' panicked at 'no entry found for key', crates/compiler/alias_analysis/src/lib.rs:1404:28
Full Backtrack
stack backtrace:
   0:        0x101284637 - __mh_execute_header
   1:        0x10066c70a - __mh_execute_header
   2:        0x10127cddc - __mh_execute_header
   3:        0x10128880b - __mh_execute_header
   4:        0x10128854b - __mh_execute_header
   5:        0x101288dbf - __mh_execute_header
   6:        0x101288d04 - __mh_execute_header
   7:        0x101287198 - __mh_execute_header
   8:        0x101288a02 - __mh_execute_header
   9:        0x10254da03 - __ZN4llvm15SmallVectorBaseIyE8grow_podEPvmm
  10:        0x1006693fb - __mh_execute_header
  11:        0x1006693ac - __mh_execute_header
  12:        0x10254d899 - __ZN4llvm15SmallVectorBaseIyE8grow_podEPvmm
  13:        0x1008b61ed - __mh_execute_header
  14:        0x1008ab26d - __mh_execute_header
  15:        0x1008a9fcd - __mh_execute_header
  16:        0x100c27cb3 - __mh_execute_header
  17:        0x10096a706 - __mh_execute_header
  18:        0x100968cf0 - __mh_execute_header
  19:        0x10096caaa - __mh_execute_header
  20:        0x10096bf15 - __mh_execute_header
  21:        0x100a3c82a - __mh_execute_header
  22:        0x1008a463c - __mh_execute_header
  23:        0x10089f0a6 - __mh_execute_header
  24:        0x10089f0c5 - __mh_execute_header
  25:        0x101276d5c - __mh_execute_header
  26:        0x1008a5caf - __mh_execute_header
  27:     0x7ff816a4d310 - <unknown>

Here's the code:

app "hello"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
    imports [pf.Stdout, pf.Http.{defaultRequest}, pf.Task]
    provides [main] to pf

main =
    request = { defaultRequest & url: "http://aaronstrick.com" }

    output <- Http.send request
        |> Task.onFail (\err -> err |> Http.errorToString |> Task.succeed)
        |> Task.await

    Stdout.line output

Note that request = defaultRequest runs fine (providing the InvalidRequest error I would expect.

Corrections for record-builder.roc

When trying to compile this there were some minor changes to make:

  • Task signature: I32 -> U32
  • Task.ok --> Task.succeed
  • Task.mapErr --> Task.mapFail

I tried to fork and do a pull request, but today the whole business with SSH keys needed for that didn't want to work for me.
So here is the update code:

app "test"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" }
    imports [
        pf.Stdout, pf.Task.{ Task },
    ]
    provides [main] to pf

main =
    myrecord : Task { apples : List Str, oranges : List Str } U32
    myrecord = Task.succeed {
        apples: <- getFruit Apples |> Task.batch,        
        oranges: <- getFruit Oranges |> Task.batch,      
    }

    { apples, oranges } <- myrecord |> Task.await        

    "Apples: "                                           
    |> Str.concat (Str.joinWith apples ", ")
    |> Str.concat "\n"
    |> Str.concat "Oranges: "
    |> Str.concat (Str.joinWith oranges ", ")
    |> Stdout.line
    |> Task.mapFail \_ -> 1

getFruit : [Apples, Oranges] -> Task (List Str) *
getFruit = \request ->
    when request is
        Apples -> Task.succeed ["Granny Smith", "Pink Lady", "Golden Delicious"]
        Oranges -> Task.succeed ["Navel", "Blood Orange", "Clementine"]

# =>
# Apples: Granny Smith, Pink Lady, Golden Delicious
# Oranges: Navel, Blood Orange, Clementine

Change `main` type to `Task {} *`

The idea here is to make main more beginner-friendly without noticeably affecting things experienced users.

If main has the type Task {} * (which it achieves by translating any unhandled Task errors into crashes automatically), then beginners don't need to learn about how to gracefully handle errors right away. They can pretty much just ignore errors and get a crash if something goes wrong, allowing them to focus on learning other things - e.g. how to chain tasks together.

Advanced users can continue to annotate their main as main : Task {} [] (which of course is compatible with main : Task {} *) and then they'll still get exhaustiveness errors for any task errors they forgot to handle, just like today!

Panics when opening a file that doesn't exists

app "example"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.1.2/3bKbbmgtIfOyC6FviJ9o8F8xqKutmXgjCJx3bMfVTSo.tar.br" }
    imports [
        pf.Stdout,
        pf.Task.{ Task },
        pf.File,
        pf.Path.{ Path },
    ]
    provides [ main ] to pf

main : Task {} []
main =
    task = 
        _ <- File.readUtf8 (Path.fromStr "i-dont-exist.txt") |> Task.await
        
        Stdout.line ""

    Task.onFail task \_ -> crash "ooops"
luke@192-168-1-108 aoc-2022 % roc dev test.roc
thread '<unnamed>' panicked at 'not yet implemented: Report a file open error', src/lib.rs:421:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5

`NetworkError` should be more specific

There can be useful data behind a NetworkError, for example:

hyper::Error(
        Connect,
        ConnectError(
            "dns error",
            Custom {
                kind: Uncategorized,
                error: "failed to lookup address information: Name does not resolve",
            },
        ),
    ),

We should not discard that kind of data.

To start of simple, we can change NetworkError to NetworkError Str.

error function suggestion

This is a very common pattern, we should probably provide a single function that does this

{} <- Stderr.line "Error: calculation failed" |> Task.await

Task.err 1

http get panic: `there is no reactor running`

❯ ./target/release/roc examples/helloWorld.roc 
thread 'main' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime', src/lib.rs:678:42
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5
app "helloWorld"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" }
    imports [pf.Http, pf.Task.{ Task }, pf.Stdout]
    provides [main] to pf

main : Task {} I32
main =

    request = {
        method: Get,
        headers: [],
        url: "http://www.example.com",
        body: Http.emptyBody,
        timeout: TimeoutMilliseconds 5000,
    }

    _ <- Http.send request
        |> Task.attempt

    Stdout.line "Done"

‼️ The timeout is the trigger here, timeout: NoTimeout does work.

args example Error in alias analysis

+ ./roc_nightly/roc build --linker=legacy ./examples/args.roc
🔨 Rebuilding platform...
thread 'main' panicked at 'Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("\x1b\x00\x00\x00\x12\x00\x00\x00\xbe\xd12$b\x077\x15"), definition of value binding ValueId(59): could not find func in module ModName("UserApp") with name FuncName("\x8c\x00\x00\x00\x12\x00\x00\x00\x1d\xca$\xf15\xe8\xd8\x98")', crates/compiler/gen_llvm/src/llvm/build.rs:5094:19

This is a recent regression in roc, I should be able to bisect this soon.

"args-example" was not provided as a first argument

$ ./target/release/roc run examples/args.roc --linker=legacy -- log -b 3 --num 81
args-example
A calculator example of the CLI platform argument parser

COMMANDS:
    div
        OPTIONS:
            --dividend, -n    the number to divide; corresponds to a numerator  (integer, 64-bit signed)
            --divisor, -d    the number to divide by; corresponds to a denominator  (integer, 64-bit signed)

    log
        OPTIONS:
            --base, -b    base of the logarithm  (integer, 64-bit signed)
            --num    the number to take the logarithm of  (integer, 64-bit signed)

The program name "args-example" was not provided as a first argument!

The weird thing is, this only happens when using a basic-cli release, not when building the platform from source.
We use the rust args_os function under the hood, in the docs it is mentioned that "The first element is traditionally the path of the executable, but it can be set to arbitrary text, and might not even exist. This means this property should not be relied upon for security purposes."

add `FileWriteErrToErrMsg` and `FileReadErrToErrMsg`

We currently have writeErrToStr and readErrToStr, but these just convert the tag name to a Str, they do not provide a high quility error message.

FileWriteErrToErrMsg and FileReadErrToErrMsg should convert each variant of a WriteErr or ReadErr to a high quality error message, for example with WasADirectory:

File write error:
    WasADirectory:
        I tried to write to:
            <path>
        but it was a directory, I can only write to a file.

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.