Coder Social home page Coder Social logo

borgo-lang / borgo Goto Github PK

View Code? Open in Web Editor NEW
3.7K 28.0 50.0 1021 KB

Borgo is a statically typed language that compiles to Go.

Home Page: https://borgo-lang.github.io

Rust 89.61% TypeScript 3.64% JavaScript 1.17% Just 0.50% CSS 0.43% Go 4.47% Nix 0.18%
compiler golang programming-language rust-lang

borgo's Introduction

The Borgo Programming Language

Borgo sits between Go and Rust


build

I want a language for writing applications that is more expressive than Go but less complex than Rust.

Go is simple and straightforward, but I often wish it offered more type safety. Rust is very nice to work with (at least for single threaded code) but it's too broad and complex, sometimes painfully so.

Borgo is a new language that transpiles to Go. It's fully compatible with existing Go packages.

Borgo syntax is similar to Rust, with optional semi-colons.

Tutorial

Check out the online playground for a tour of the language.

You can also take a look at test files for working Borgo code:

Features

Algebraic data types and pattern matching

use fmt

enum NetworkState {
    Loading,
    Failed(int),
    Success(string),
}

let msg = match state {
    NetworkState.Loading => "still loading",
    NetworkState.Failed(code) => fmt.Sprintf("Got error code: %d", code),
    NetworkState.Success(res) => res,
}

Option<T> instead of nil

// import packages from Go stdlib
use fmt
use os

let key = os.LookupEnv("HOME")

match key {
    Some(s) => fmt.Println("home dir:", s),
    None => fmt.Println("Not found in env"),
}

Result<T, E> instead of multiple return values

use fmt
use net.http

fn makeRequest() -> Result<int, error> {
    let request = http.Get("http://example.com")

    match request {
        Ok(resp) => Ok(resp.StatusCode),
        Err(err) => Err(fmt.Errorf("failed http request %w", err))
    }
}

Error handling with ? operator

use fmt
use io
use os

fn copyFile(src: string, dst: string) -> Result<(), error> {
    let stat = os.Stat(src)?

    if !stat.Mode().IsRegular() {
        return Err(fmt.Errorf("%s is not a regular file", src))
    }

    let source = os.Open(src)?
    defer source.Close()

    let destination = os.Create(dst)?
    defer destination.Close()

    // ignore number of bytes copied
    let _ = io.Copy(destination, source)?

    Ok(())
}

Guessing game example

Small game from the Rust book, implemented in Borgo.

Things to note:

  • import packages from Go stdlib
  • strconv.Atoi returns an Option<int>
  • Reader.ReadString returns a Result<string, error> (which can be unwrapped)
use bufio
use fmt
use math.rand
use os
use strconv
use strings
use time

fn main() {
    let reader = bufio.NewReader(os.Stdin)

    let secret = rand.Intn(100) + 1

    loop {
        fmt.Println("Please input your guess.")

        let text = reader.ReadString('\n').Unwrap()
        let text = strings.TrimSpace(text)

        let guess = match strconv.Atoi(text) {
            Ok(n) => n,
            Err(_) => continue,
        }

        fmt.Println("You guessed: ", guess)

        if guess < secret {
            fmt.Println("Too small!")
        } else if guess > secret {
            fmt.Println("Too big!")
        } else {
            fmt.Println("Correct!")
            break
        }
    }
}

Running locally

Borgo is written in Rust, so you'll need cargo.

To compile all .brg files in the current folder:

$ cargo run -- build

The compiler will generate .go files, which you can run as normal:

# generate a go.mod file if needed
# $ go mod init foo
$ go run .

borgo's People

Contributors

a10y avatar alpacaaa 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

borgo's Issues

Functions that return single error

I was writing definitions for os/exec and stumbled upon functions that return single error.
Example:
https://pkg.go.dev/os/exec#Cmd.Run

func (c *Cmd) Run() error

Run() returns error if error happened, otherwise returns nil.
I tried wrapping error in Option. But that assumes that there is second bool return argument.
Then I tried using Result<()>, but still it assumed that there are two return arguments.

What should I use for this use case?

fun as function keyword to line up code better

Small pet peeve: I never understood why Rust (not to mention Go) didn't go with fun as the keyword for functions, so that the function name lines up with four space indentation of the code below ๐Ÿ˜Š

So instead of:

fn main() {
    let reader = bufio.NewReader(os.Stdin)

    rand.Seed(time.Now().UnixNano())
    let secret = rand.Intn(100) + 1
    // ... cont ...

We'd have:

fun main() {
    let reader = bufio.NewReader(os.Stdin)

    rand.Seed(time.Now().UnixNano())
    let secret = rand.Intn(100) + 1
    // ... cont ...

Just to say how great this project is

While I'm not looking for a solution like this for my own work (I'm happy using Rust), I want to congratulate you on it. It addresses the weaknesses in Go and the design decisions are excellent.

It also fills a need for what is many times discussed on the Rust forum, which is a language like Rust that has GC and is much simpler to use, Of course, Rust people would prefer Rust semantics rather than Go semantics, but I see that as a relatively minor issue.

Of course, to make this usable there are tons of tools need, LSP, etc. I hope there are people in the Go community who are motivated to help with this.

Generate binary

  • It would be nice if Borgo compiler went a bit further and generated the compiled go code.
  • Of course this would require having go toolchain installed, but IMHO would be a nice dev UX
  • BTW...this project looks super cool!

Can io.Reader's Read safely return Result<int>?

The definition of Read in io.Reader is currently fn Read (p: [byte]) -> Result<int>. I believe this limits it to returning only one of the number of bytes read or an error. But this does not reflect what Read does. From go's docs, Read "returns the number of bytes read (0 <= n <= len(p)) and any error encountered" (emphasis added). There is further discussion of this in several golang-nuts threads such as this one.

(Apologies if I misunderstood something here. I know more go than rust, and I ended up here thanks to an interesting-sounding link from go weekly news.)

generates code with invalid generics when calling helper functions

The following borgo code:

use fmt

struct foo<T> {
    val: T
}

impl<T> (f: foo<T>) {
    fn print() {
        printHelper(f)
    }
}

fn printHelper<T>(f: foo<T>) {
    fmt.Println(f.val)
}

fn main() {
    let f = foo{val: 5}
    f.print()
}

generates:

package main
import (
 "fmt"
)

type foo[T any] struct {
  val T
}
 func (f foo[T]) print  ()  {


 printHelper[any](f)
}
 func  printHelper [T any] (f foo[T])  {


 fmt.Println(f.val)
}
 func  main  ()  {


f := foo[int] { val: 5,  }

 f.print()
}

The issue here is that the line that reads printHelper[any](f) should read printHelper[T](f).

I can't find a way to get borgo to generate compiling Go code for this case.

Monadic chaining of calls

Is it possible to add iterators for slices so we can do pipeline like operations?
a := [1,2,3,4]
b := a | filter() | transform(f) | sum()

Add executable to cargo/brew

It would be great to add this tool to either cargo or brew (ideally both) to make it easier to install. As part of that, the compiler program should probably be renamed to just borgo

How to import external package

borgo's importer tool can import go std package and user's package, but how to impot other external package:
in golang i can:

import "github.com/go-chi/chi/v5"

the corresponding usage in borgo:

use "github.com/go-chi/chi/v5"

or

use github.com/go-chi/chi/v5

neither works, how to import other package using borgo's importer tool, and how to use?

Capture in the lambda, causes stack overflow (?)

Not sure what is the root cause of the issue, but compiling these code leads to stack overflow:

use fmt

struct Iterator<T> {
    next: fn() -> Option<T>
}

fn iter<T>(list: [T]) -> Iterator<T> {
    let mut i: int = 0
    Iterator { 
        next: || {
            if i < list.Len() {
                let x = list[i]
                i = i + 1
                Some(x)
            } else {
                None
            }
        },
    }
}


fn main() {
    let xs = [1, 2, 3, 4, 5]
    fmt.Println(iter(xs))
}

Possible causes:

  1. Because I am trying to mutate i, compiler freaks out
  2. Some ungodly reason that is beyond my comprehension

But, I tried to remove the logic from the lambda, and got following error

fn iter<T>(list: [T]) -> Iterator<T> {
    Iterator { 
        next: || {
            None
        },
    }
}

.\main.go:12:28: cannot use func() (T, bool) {โ€ฆ} (value of type func() (T, bool)) as func() Option[T] value in struct literal
when trying to compile the go code.

Here is the snippet from main.go:

type Iterator[T any] struct {
  next func () Option[T]
} 
 func  iter [T any] (list []T) Iterator[T] {


return Iterator[T] { next: func () (T, bool) {



        if make_Option_None[T]().IsSome() {
            return make_Option_None[T]().Some, true
        }
        return *new(T), false
              
},  }  
}

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.