Giter Site home page Giter Site logo

flax-lang / flax Goto Github PK

View Code? Open in Web Editor NEW
146.0 10.0 10.0 5.38 MB

general purpose programming language, in the vein of C++

License: Apache License 2.0

C++ 98.15% Makefile 0.37% Batchfile 0.01% Python 0.37% Meson 1.06% PowerShell 0.05%
llvm language c-plus-plus language-design flax compiler programming-language

flax's Introduction

A low level, general-purpose language with high level syntax and expressibility.

forthebadge forthebadge

build status      build status      Build Status


Disclaimer

I work on Flax in my spare time, and as the lone developer I cannot guarantee continuous development. I'm no famous artist but this is my magnum opus, so it'll not be abandoned anytime soon.

Language Goals

  • No header files.
  • Minimal runtime
  • Minimal stupidity
  • Clean, expressive syntax

Current Features

  • Structs, unions, enums
  • Arrays (fixed and dynamic), slices
  • Pointer manipulation/arithmetic
  • Operator overloading
  • Generic functions and types
  • Type inference (including for generics)
  • Full compile-time execution (of arbitrary code)
  • Classes, including virtual dispatch and (single) inheritance

Language Syntax

  • We don't have a proper place that documents everything yet, but most of the basic stuff is probably not gonna change much. The testing code in build/tests/ (most of them, anyway — check tester.flx to see which ones we call) tests basically 90% of the language, so that's the syntax reference for now.
  • Yes, the syntax is not "officially" defined by a grammar. The reference parser implementation is the One True Definition, for now.

Code Sample

import std::io as _

@entry fn main()
{
	println("hello, world!")
}
do {
	fn prints<T, U>(m: T, a: [U: ...])
	{
		for x in a => printf(" %.2d", m * x)
	}

	printf("set 6:")
	let xs = [ 1, 2, 3, 4, 5 ]
	prints(3, ...xs)

	printf("\n")
}

do {
	union option<T>
	{
		some: T
		none
	}

	let x = option::some("foobar")
	let y = option::some(456)

	println("x = %, y = %", x as some, y as some)
}

Building the Flax compiler

Dependencies

  • LLVM 11, mostly due to their obsession with changing the IR interface every damn version
  • GMP/MPIR
  • MPFR
  • libffi

macOS / Linux

  • The makefile is the preferred way to build on UNIX systems.
  • LLVM needs to be installed. On macOS, brew install llvm should work, and you might need to do some PPA fiddling for Debian-based distros.
  • A C++17-compatible compiler should be used.
  • Find the flaxc executable in build/sysroot/usr/local/bin.
  • Additionally, the (admittedly limited) standard library will be copied from ./libs to ./build/sysroot/usr/local/lib/flaxlibs/.

Windows

  • Install meson.
  • Run env MPIR_ROOT_DIR=... LLVM_ROOT_DIR=... meson meson-build-dir to set the locations for the dependencies (see meson.build for the names, there are 4) and configure the build.
  • Optionally, pass --buildtype=release to build a release-mode compiler (highly recommended).
  • Run ninja -C meson-build-dir.
  • flaxc.exe will be found in the build directory.
Libraries
  • Download the prebuilt binaries for the 4 dependencies, and place them somewhere.
  • Note: the folder structure of the libraries should be (llvm|mpir|mpfr|libffi)/(Release|Debug)/(include|lib)/....

Building Flax Programs

Since nobody in their right mind is actually using this, please pass -sysroot build/sysroot to invocations of the compiler -- else the compiler will default to looking somewhere in /usr/local/lib for libraries. Speaking of which, standard libraries are looked for in <sysroot>/<prefix>/lib/flaxlibs/. Prefix is set to /usr/local/ by default.

Since version 0.41.2, executables can be generated on all 3 of our supported platforms! For Linux and macOS, all that is required is a working C compiler in the $PATH; we call cc to link object files.

For Windows, even if you are not building the compiler from source (eg. you are using a released binary), Visual Studio 2017 or newer must still be installed, with the "Desktop development with C++", "MSVC v142 (or whatever)", and "Windows 10 SDK" components. However, we currently find the toolchain through established means, so that link.exe does not have to be in the %PATH%, ie. you do not have to call vcvarsall.bat before running the compiler.


Contributors

Special thanks to the Unofficial Official Language Consultants: darkf, adrian17, sim642, and ryu0.

Contributing

Feel free to open an issue if you feel that there's any missing feature, or if you found a bug in the compiler. Pull requests are also welcome.

Licensing

The Flax compiler itself (this repository) is licensed under the Apache 2.0 license (see LICENSE file). For ease of building, some dependencies are included in the repository itself (under the external folder) and compiled together, instead of as a separate library (shared or otherwise). These are:

  1. mpreal, GPL
  2. utf8rewind, MIT
  3. tinyprocesslib, MIT

flax's People

Contributors

adrian17 avatar philpax avatar tobiasvl avatar zhiayang 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

flax's Issues

Inline type declarations

Potentially allow something like this:

var s: struct {
	x: int
	// ...
}

what are these called, voldermort types? can substitute named tuples in other languages i suppose. Also need to investigate if this is useful for enumeration types (the cases aren't placed into global scope, so idk how you'd refer to them)

Lack of union types

Unsure if this is intentional or not, but there doesn't seem to be any facility for creating unions in the language spec (from the website) or in the compiler.

I posit this is useful, because:

  1. A systems language should have unions, as storing values of different types in the same memory space is important for efficient memory usage
  2. Porting code from other languages with unions (especially C) is infeasible without them. The relevant data members could be type-punned using pointer type casting, but this doesn't scale well and complicates porting

Slices and printfs

Currently the compiler automatically converts a str to its pointer when passing it to a C-style vararg function (eg. printf) (see

// auto-convert strings and char slices into char* when passing to va_args
)

Of course this kinda defeats the purpose, since slices are not necessarily null-terminated. The proposed alternative (which I'm proposing now) is to pass the entire struct to printf, which will cause it to get both the length and the pointer.

(aside: the layout of str is like this: struct str { len: i64; ptr: &i8 })

Then, we would need to call printf with %.*s instead of just %s.

Scoping Rules

The whole importing/modules/namespaces thing needs a bit of work to be useful. Top on the list: using namespace.

Right now all types and functions in namespaces/static functions in classes have to be fully qualified, which is clearly a pain. Some kind of using construct is important for usability.

Next, public vs private imports. Right now importing something exposes it to everybody who imports you. I'm using that behaviour in the libraries right now, but that shouldn't be the case (by default anyway).

Propose something like public import ... and private import ..., where the latter is the default behaviour, and does not "re-export" whatever was imported.

Also, allow importing modules under their own namespace, eg.
import lib.somefoo as foo to use foo.topLevelFunction() instead of polluting the global namespace.

Also, then: should that automatically put all the top level things from somefoo into a namespace somefoo, or leave it at top-level?

Finally: allow importing files directly by using a string instead of a bunch of dot-operator things.

Deferred statements should capture state of variables

Basically

func thing()
{
    var x = 1;
    defer printf("%d\n", x);
    x = 2;
    // deferred statement runs here, outputs 1
}

The defer statement should capture the state of variables etc. at the point of declaration. This ought to include all global state, as well as local state (stack variables). Might be non-trivial, especially to capture program state as a whole. If x above was a global variable instead, it would be a lot harder to capture.

If data/control flow analysis gets sufficiently implemented, it could be possible to trace the mutability of any given global variable (ie. is it ever assigned to or modified between the declaration of the defer and the execution of it), and only capture non-const variables that have the possibility of changing. Not sure if worth it or not. This would also need to consider volatile variables, and always include them.

Finally, it will definitely be non-trivial to ensure that global state across modules is captured as well. This might not even be possible without going through a number of hoops in the code generation stage (more passes anyone?)

There is of course the option of simply not capturing global state at all. It makes our lives easier, but will be less predictable for programmers, since the global state might have changed between the time the defer statement is declared and when it is executed. Would a warning suffice if the user uses a global variable in a deferred statement?

Semaphore CI Build

Semaphore 1.0 still uses Ubuntu 14.04 LTS on their platform which was EOL-ed on April this year. The LLVM APT repositories are no longer available for Ubuntu Trusty, so we cannot build.

It's the CI with the fastest turnaround (from commit to success), so that's pretty sad. I've sent them a support ticket, we'll see if it does anything.

llvm binaries

On windows specifically how and where do we get the libllvm binaries from or do we compile them from source because i am probably missing something obvious

better to use a Makefile than the Capri build system

Hey

so i'm not too good at the whole build thing, but I think you should use a makefile instead of the capri thing. it makes it easier for people to compile and use since most *nix systems already have the make command built-in. Just a suggestion though.

Cheers

enumerations are completely broken

obviously i had 0 foresight when redesigning the enum system during the rewrite. they're not completely unusable currently, but only if you restrict yourself to flax code. For interoperating with C code, because enum case values are a 2-word struct, they become dumb.

we need the idea of a @raw enum that is literally a typesafe value, without any of that struct wrapping stuff with the index or whatever. Of course you lose type information, but it's not like we have any type introspection in the language now anyway.

Class inheritance is source-order-dependent

Basically, your base class must appear in the source code before your derived class. This will not work:

class A : B
{
    // ...
}

class B 
{
    // ...
}

Which is contrary to how the rest of the language works.

A way to check for non-simple types with `is`

We can currently do if (x is T) if T is some primitive-ish type like i64 or str or even a user-defined struct. Unfortunately we cannot match x with something like [T], although I suppose that requires proper generics of some sort.

Code Path Analysis (ensure all code paths return a value)

This might be a bit non-trivial to implement, but I want to catch this error in the frontend, rather than letting LLVM fire an assert.

Basically this involves simulating all possible branches, ensuring that all ifs, switches etc. Have a return value.

This will also let us have the implicit return.

Compile time assignments of runtime variables triggers assert

If you assign a runtime variable inside a #run directive, it triggers an assert and crashes the compiler

@entry fn main() {
    var i = 0
    #run(
        i = 34 // uwu
    )
}

this results in

compiler assertion at source/fir/interp/interpreter.cpp:1369, cause:
'ret' evaluated to false


there were errors, compilation cannot continue

Better Error Checking and Warnings

Right now, the Flax frontend doesn't catch all the errors and edge cases of poorly formatted code. This causes various assertions to fire (mostly in LLVM code, although I've had a few cases where some of my own got hit).

The problem is that LLVM errors are very often cryptic and don't help anybody -- they also don't provide proper positional info to the end-user.

Also, the frontend currently does not issue warnings, which might be useful.

Paradigm

Please add

Metalinguistic abstraction,
Set theoretic programming,
And tacit programming

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.