jfecher / ante Goto Github PK
View Code? Open in Web Editor NEWA safe, easy systems language
Home Page: http://antelang.org
License: MIT License
A safe, easy systems language
Home Page: http://antelang.org
License: MIT License
ante (master??!) $ make
Generating parser...
In file included from include/parser.h:8:0,
from include/ptree.h:4,
from src/syntax.y:8:
include/compiler.h: In member function ‘int DataType::getFieldIndex(std::__cxx11::string&)’:
include/compiler.h:56:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i = 0; i < fields.size(); i++)
^
src/parser.cpp: At global scope:
src/parser.cpp:4734:1: fatal error: opening dependency file obj/parser.d: No such file or directory
} // yy
^
compilation terminated.
Makefile:43: recipe for target 'obj/parser.o' failed
make: *** [obj/parser.o] Error 1
system:
Linux mint-kitty 4.4.0-23-generic #41-Ubuntu SMP Mon May 16 23:04:25 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
type Maybe = | Some u8
works fine.
type Maybe = | Some u8 | None
breaks.
Will there be possibility to disable use of global variables (dangerous ones, modified during runtime)? Either per project or when a module is imported.
Using the same code as #39 , but replacing with a tuple match and extract:
Printing the value of the u8
in Some
always gives the length of the string, and not the value passed in to the constructor.
When given bitcode containing a function returning a non-constant tuple, llc stalls and exponentially increases memory usage. This does not seem to occur if all elements except for the last is constant in the returned tuple. Example problem code:
i32,i32 toTuple: i32 a b
return (a, b)
let tup = toTuple(2, 3)
When a tuple of four or more elements is returned instead, instead of llc stalling, the optimization passes for the function crash instead. The specific pass that crashes is:
X86 DAG->DAG Instruction Selection
This currently fails:
var foo
if 2 > 1 then
foo = 0i8
else
foo = 1i8
Will this be eventually supported?
I was not able to make Ante...when I looked at pacman on arch, it clearly showed as having LLVM 3.9.1 installed.
But when I did lli --version, the version I got back was 3.6.2.
I found out 3.9 is installed in /usr/bin while 3.6.2 is installed in /usr/local/bin.
I've not been able to find how to either remove 3.6.2, or set it up so that 3.9.1 gets used instead.
Any pointers would be greatly appreciated....no pun intended.
Maybe I'm misunderstanding some basic syntax here
type Box<'t> = 't contents
printf "%d" (Box 1u8).contents
This program segfaults at compFnCall
line 1001, apparently because val
is NULL
on a TypedValue
.
Interestingly, this doesn't happen if you leave out the printf
- just (Box 1u8).contents
compiles fine. Could this be an issue with the type inference?
Currently name is just a text and what characters it contains doesn't matter to the compiler, as long as they are from valid range.
How about possibility, to specify in project configuration that certain format of names implies certain property of its bearer.
Few examples:
if name ends with ? it is bool variable or function returning bool. Spaniards may want ¿ at the beginning and ? at the end.
if function name ends with ! then it means the function has no side effects
if someting is a macro it may start with #
private names start with lowercase, public with uppercase (ala Go).
stdlib and 3pp sources may get preprocessed and characters not specified in project config preprocessed out, lowercase/uppercase replaced by pub/priv, etc.
These things, rules of formatting and naming, may sound trivial, but they are often contentious and deter people from reusing other's code, "because ugly and nonconforming".
For me, functional style primarily means "function uses only immutable parameters, doesn't touch anything global". Wouldn't it make sense to support this functionality by the language?
Specifically:
Definition of such function could be distinguished from ordinary impure function. E.g. fn
instead of fun
, or having proc
and fun
or something.
Invocation syntax. It should be clear on the first sight that a pure function is being called, not an ordinary one. E.g. using double parenthesis for such call, my_fun((par1, par1))
, or inverted parenthesis, my_func)par1, par2(
, or something.
This gives a TypeVarError; lookup for 't not found
Box<'t> = 't contents
BoxedBox<'u> = Box<'u> box
This might be more of a feature request than a bug.
I am not sure on if this is an error or if I am doing something wrong:
$ cat test.an
print "Hello World!"
$ ./ante_x86_64_unix -r test.an
/usr/bin/ld: test.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
sh: 1: ./test: not found
ubuntu 16.10
$ ldd ante_x86_64_unix
linux-vdso.so.1 => (0x00007ffe3e717000)
libLLVM-4.0.so => /usr/lib/x86_64-linux-gnu/libLLVM-4.0.so (0x00007f9a9ce38000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9cab0000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9c7a7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a9c590000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a9c1c9000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f9a9bfbf000)
libedit.so.2 => /usr/lib/x86_64-linux-gnu/libedit.so.2 (0x00007f9a9bd87000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9bb83000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f9a9b95a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9b73c000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f9a9b522000)
/lib64/ld-linux-x86-64.so.2 (0x00005607270ed000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f9a9b30b000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f9a9b103000)
Thank you for making ante public for the public to experiment with, to me it looks like a really interesting combination of memory efficiency and clean and expressive syntax.
I have file:
print "Start\n"
print "End\n"
where the last line DOES NOT end with newline.
The result:
O:\ante\ante-master\bin>ante test2.an
←[;3mtest2.an←[;m: ←[;1m3,7-15←[;0m ←[;31merror: ←[;mCalled function was given 2 arguments but was declared to take
1
print "End\n"
←[;31m ^^^^^^^^^←[;m
Compilation aborted.
example code:
if true then
puts("branch 1")
else
puts("branch 2")
compiled with --emit-llvm -O0
produces:
@0 = private unnamed_addr constant [9 x i8] c"branch 1\00"
@1 = private unnamed_addr constant [9 x i8] c"branch 2\00"
define i8 @main() {
entry:
br i1 true, label %then, label %else
then:
call void @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @0, i32 0, i32 0))
br label %endif
else
call void @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @1, i32 0, i32 0))
br label %endif
endif:
phi void [ <badref>, %then ], [ <badref>, %else ] ; <---- this line
ret i8 0
}
Gcc and clang (and I guess LLVM bitcode too) support hint __builtin_expect
to the compiler. The hint is usually wrapped within macros:
if (likely(..)) { ... }
if (unlikely(...)) { ... }
and it has some minor impact:
http://blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html
Why not support such featurette directly in the language? E.g.
if+ x > y then ... // here we expect the condition to be true most of the time
if- x > y then ... // we expect almost never go this way
if x > y then ... // no idea or random chance
The feature may also serve as very succint documentation, this could be arguably the most useful function.
If Ante will ever have profile guided instrumentation it may detect clearly mistaken hints and show warning to the user, that his expectations were wrong.
elif
may use this trick too. if-x
would be compiler error.
I have few questions and don't know better place where to ask.
type Char = c8|c32 c
:
Is this union like in C, without any hidden tag? How are ambiguities resolved? Say:
type foo = i8 | i16
var foo bar = i8 10
var i32 baz = bar
ranges:
for u in 0 ..^ testArr.len() do
print(testArr#u)
Will the testArr.len()
be called repeatedly or will the compiler inspect the body of for
and move it out?
Type condition errors:
type Teen =
u8 age in 10 .. 19
Str name where name.length > 0
//TypeConditionErr
let sara = Teen(18, "")
If the condition is not true during runtime what will happen? Is/will there be some way to disable the check either explicitly or because some checking actions made before?
In language.am
there's sentence "TypeConditionErr is thrown". I though exceptions are not in the language.
I tried to compile the tiny test:
print "Start"
let x1 = 250u8
print x1
print "End"
Screenshot of the result:
http://i.imgur.com/p1svZPF.png
Got 2 small problems:
O:\ante\ante-master\bin>ante test.an
test.an: 5,7-8 error: Argument 1 of function is a(n) u8 but was declared to be a(n) c8* and there is no known implicit
cast
print x1
^^
Compilation aborted.
I'm testing out pattern matching on tags, and the following code gives me an error:
type MaybeIntStr =
| Some u8, Str
| None
fun printmis : MaybeIntStr m
match m with
| Some i string -> printf "%d and %s" i string
| None -> print "None"
let s = Some(1u8, "test")
printmis(s)
I can't replace i string
with i, string
without syntax errors, but trying to compile this as is gives the error pattern typecast's rval is not a identifier
. My own debugging seemed to suggest that the compiler was taking i string
as a single variable name instead of splitting it up. What should I be doing?
Will Ante support namespaces? If you are interested I have idea how to make them better than e.g. in C++.
String interpolation: will it be possible to "intercept" this mechanism for certain specific cases? What I have in mind is advanced assert:
assert(x > 0, "x = ${x}, y = ${y}, z = ${z}")
If assert happens I would like to use my own memory handling management when showing all these details, w/o worrying about accidentally running out of memory.
https://github.com/jfecher/ante/blob/master/stdlib/prelude.an#L46
I think it should be usz...
In file strInterpolation.an
I noticed line:
print( "Hello, " ++ getMyString() ++ "!")
Why is the ++
needed here? These string has to be concatenated, nothing else can be done here. Why not the ability to omit this operator when the context is clear (and it is also clear where expression ends)?
print( "Hello, " getMyString() "!")
This would help e.g with generating HTML fragments, making it easier to the eyes.
Say I have:
type Char = c8|c32 c
let Char ch = ...
Does the language support "polymorphic use" through union parameters? Say I have functions:
fun foo: ch8 par = ...
fun foo: c32 par = ...
// Now the compiler may insert run-time decision
// which function to call.
// It could also do compile-time check that all possibilities are covered,
// that there's a foo overload for every union member
//
foo(ch) // will this work?
type Bt 't =
| Branch 't,'t
| Leaf 't
let l = Leaf 3
let b = Branch(l, l) //good
let invalid = Branch(l, 3) //invalid but type checker allows it and inferences Bt (Bt i32)
The code above is accepted by the compiler, but should be rejected as Branch(l, 3) should not match the data definition of Branch 't, 't
When evaluating 255_u8 + 1234_u16
the compiler translates this incorrectly to the signed addition of -1 and 1234, resulting in 1233 instead of the desired 1489.
Attempting to call any ![macro]
function in windows crashes the compiler.
printing 5/2 yields the correct value of 2, but printing -5/2 yields -3
Do you want a pull request for properly bootstrapping obj/f16.ao?
e.g. darwin has no ELF.
roughly like this (but see #31):
--- Makefile
+++ Makefile
@@ -35,8 +35,10 @@ DEPFILES := $(OBJFILES:.o=.d)
.DEFAULT: ante
ante: obj obj/parser.o $(OBJFILES) $(ANOBJFILES)
- @echo Linking...
- @$(CXX) obj/parser.o $(OBJFILES) $(ANOBJFILES) $(LLVMFLAGS) -o ante
+ @echo Linking...
+ @$(CXX) obj/parser.o $(OBJFILES) $(LLVMFLAGS) -o ante
+ @$(MAKE) obj/f16.ao
+ @$(CXX) obj/parser.o $(OBJFILES) $(ANOBJFILES) $(LLVMFLAGS) -o ante
But there's more missing. ante needs to be called as ./ante unless you already bootstrapped it into the PATH.
And darwin needs make YACC=/opt/local/bin/bison
as /usr/bin/bison
is too old.
I've been trying to write a basic linked-list, but the type system doesn't accept the recursion. Is a forward declaration required?
I don't know if this is an oversight of the type system, but trying to compile this on my machine makes a segfault.
Box<'t> = 't* contents
let b = Box 1u8
printf "Box contents: %d" (@b.contents)
Obviously the box instance isn't well-typed and the pointer type isn't determinable, which might be causing the issue. let b = Box (new 1u8)
works as expected.
Also interesting: if you try to use string interpolation, print "Box contents: ${(@(b.contents)}"
identifies that the type of b.contents
is actually 't*
, and it complains that this isn't a Str
. Is the type somehow valid without all the parameters being set?
The file language.an contains line:
arr -= 3 //Note: this will throw an exception if the array's size becomes < 0
What does it mean exception here? Application crash or something ala C++ with exception hierarchies and various levels of exception safety? This word is not mentioned anywhere else in the spec.
The following program gives me a segfault.
type TestType = u8 contents
fun printcontents: TestType t
printf "%d" t.contents
printcontents(TestType(1_u8))
gdb points to the culprit being line operator.cpp line 653, where extTy is null, for some reason.
Currently underscore is supported as visual separator of digits.
I remember that in some language (I forgot which one) they use ' (single quote) for this exact purpose.
Perhaps this could be per-project option. Default could be underscore, and in project configuration one could remove it or other separator(s).
If the model of "preprocessing" sources according to requested style is adopted then separators in stdlib could be "fixed" too.
In theory it would be also possible to fix number formatting according to culture, say from 1,2 to 1.2.
type Basic = | First u8 | Second u8, u8
// Fails
let b = First 1u8
// Also fails
let b = First(1u8)
// Fine
let b = Second(1u8, 1u8)
Attempting to create a First
in the let binding produces the error message Invalid type cast u8 -> First
.
Not sure what's actually causing this one. MRE:
type Tagged = | A
let a = A()
It would be nice if the repl used editline or readline or something like that so there could be history search and left/right arrows. I can make a pr if you're interested.
This example got me thinking:
type Teen =
u8 age in 10 .. 19
Str name where name.length > 0
//TypeConditionErr
let sara = Teen(18, "")
How much useful is this feature?
I'll ignore simpler things like pointer nulability checking and enforcing integer ranges and will write about string restrictions and more complicated compile time checks.
Programs usually do not have that many literals in code. Complex data are read from some external source, not hardcoded. Even hardcoded strings may go first through internationalization layer.
The checking won't be so simple.
Instead of where name.length > 0
one may want a function which decides that Jon Snow
is a valid name and ougs872kjgs
is not. One would not create such a complicated function only for rare compile time use.
Complicated checks also take time and one may not want compiler to insert them automatically, e.g every time a structure is copied. (This is IMHO the main problem with language level preconditions, postconditions and class invariants: they are nice and all but get invoked over and over, even when one knows this is unneccessary.)
I am curious how numeric expression work in ante:
print "Start"
let x1 = 250u8
let x2 = 250u8
let x3 = 250u8
var x4 = 999u8
x4 = (x1 * x2) / x3
printf "x4 = %u\n" x4
print "End"
The result is 0, instead of the correct 1. Perhaps expressions should automatically (unless it can be proved overflow cannot happen) use the highest hardware supported numeral type to avoid quiet overflows and truncating. It is different from C rules but it should not be much slower.
Alternatively the C-like truncation may be default but with option to override it with something like:
no_overflow {
.. calculations
} else {
... overflow/truncation happened
}
IIRC C# uses someting like this.
Calling a Type's init method results in the method being recompiled each time it is called. The code:
type T = i32 i
fun T.init := T 0
let p = T()
let q = T()
Results in a binary containing the functions Pair_init
and Pair_init.1
, both copies of each other.
print "Start"
let x1 = 250u8
print x1
print "End"
Compiles OK, generates the executable, this one prints the "Start" and then crashes (Windows shows dialog about problems, blah, blah).
Using ![macro]
functions on windows that call non-ante functions (such as puts
) often results in an error message:
LLVM ERROR: Tried to execute an unknown external function: puts
According to this stack overflow answer, the dlsym linking ante currently relies on is unavailable in windows:
LLVM will use dlsym() to find the symbols in the JIT program itself. Depending on your platform, [...] it might not be available at all (such as on Windows).
This is (only half baked) idea to unify static and dynamic arrays use. Static arrays and dynamic arrays (vectors) usually have different syntax leading to manual duplication of generics. Static ones are prone to degradation to pointers.
Reading language.am
I think they are distinct now (because of the array -> pointer conversion).
Whether array is static or dynamic can be (I guess) deduced from its declaration. This information can be then used by the compiler.
If a function has static array as a parameter it would also secretly pass the known fixed size as parameter and current size as another one (I think this is needed to implement the ++= operator).
If a function has dynamic array as a parameter it would take pointer to its "vector" structure.
If a function is called with static array in one place and with dynamic array in another then the code (either source or AST) would be cloned and modified to handle both variants. Similarly for templates, they would be instantiated according to their use.
If a function has several array parameters then clones would be created for all combinations which were found.
Taking pointer to such functions would not be allowed by the compiler (because the clones cannot be distinguished by name).
Array as member of structure/tuple would not require any special handling.
If implemented then conversion of arrays to pointers could be perhaps dropped (except for FFI) and pointer arithmetic as well. I had never used pointer arithmetic anywhere but in degraded array context.
I do not have clear picture for multidimensional array. (I never used such a beast.)
Few suggestions to improve enums.
match
on enums should require complete list of values, w/o the default (default would defeat the intention and may result in bug when another enum item is added later).
Some enums may want to use global namespace (like in C):
enum foo -> .Bar .Baz
(accomplished by the leading dot)
Both Bar
and foo.Bar
would be valid names. If the enum is very important for the application and used often short name is enough.
Enum may be assigned string, to be directly usable in string context:
enum Foo ->
bar = "My Name 1"
baz = "My Name 2"
Default would be the stringified symbol. Empty string or nil may mean no automatic stringification.
Aliases. This may be useful for SCADA applications where some cryptical names from the documentation have informal aliases.
enum Foo ->
NR_27_F7_3 = wheel
NR_00_H2_0
NR_12_O3_1 = engine
Formal name and alias could be used interchangeably.
Enums may be defined "inline" together with related functions, to give a hint that these constructs belong together.
// when return value is anonymous enum
fun foo -> enum Bar Baz // namespace of Bar & Baz is foo
var res = foo()
match res with
foo.Bar ->
foo.Baz ->
and
// when parameter is anonymous enum
fun foo : (enum Bar Baz) param =
foo(Bar)
and non-anonymous variants
fun foo -> enum xyz -> Bar Baz
var foo.xyz res = foo()
fun foo : (enum xyz -> Bar Baz) param
foo(xyz.Bar)
Non-anonymous inlined enums would need to be used in "function context", meaning inside the block which calls the function, not separately or as a member of some structure. Restriction on use of the symbol should avoid misuse.
Enum as valid integer range plus sideband value(s):
enum FooResult ->
NO_MEMORY // automatically assigned value outside valid result range, e.g. 101
SOME_OTHER_ERROR
1 .. 100 // valid results
fun foo -> FooResult = ...
match foo() with -> // exhaustive match
1 .. 50 ->
51 .. 100 ->
NO_MEMORY ->
SOME_OTHER_ERROR ->
Here foo()
may return valid result (the number) or error. No need to create complicated types which need more memory or to pretend that some magic number (-1) means error and hope programmer won't forget about it.
Complex example:
enum Foo ->
Bar = 1 = something = "Bar"
Baz // = 2 = "Baz"
Grr = "Hmm" // = 3
Frr = .wheel // = 4 = "Frr", 'wheel' symbol is in global namespace
Currently in Ante, the only way to initialize objects is with the typecast syntax Type val
. Initializing larger objects with several fields is done by casting a tuple to the desired type: Type (val1, val2, ..., valN)
. This syntax is not ideal for larger types. In the Vec
example below, it is difficult to tell if the len
or cap
field is being initialized to 0u32
without memorizing/referencing the Vec
type. With the new syntax, the type is free to change the ordering of its fields.
The new syntax proposed here is in addition to the current syntax and does not introduce any new keywords. It is meant for the initalization of larger objects, and enforces named fields initialization rather than initialization by the order of the arguments.
type Vec 't = ['t] data, u32 len cap
Vec([8 u32](), 0u32, 8u32)
type Vec 't = ['t] data, u32 len cap
Vec with
data = [8 u32]()
len = 0u32
cap = 8u32
This is feature suggestion based on the first (and shallow) reading of the spec.
Problems which it may solve:
Imagine a new project. Developer states (perhaps in a project specification file) that he wants to use parenthesis and underscored_names
everywhere. The compiler looks up actually imported files from standard library (and 3rd party libraries), modifies them according to the wish and copies them somewhere into the project directory. Developer then sees only code formatted according to his wishes.
The libraries would need to be written in form that allows automatic conversion.
Possibilities for problem 3: Python style, C parenthesis with different styles where to place the brackets, perhaps even Ruby style.
Possibilities for problem 2: CamelCase, Ada_Style, underscores_everywhere, possibly also style-with-minuses-as-separators. Case may or may not be made significant. Language keywords may be converted into uppercase.
Syntax should be provided for names which cannot be written in different way for whatever reason, e.g. !!
prior the name or at the top of library.
The compiler may even enforce use of given style (ala gofmt).
Problem 1 can be solved this way:
Library writer would announce features which can be selectively enabled, something as:
fetaures
{
MY_FEATURE1 "short description"
MY_FEATURE2 "description"
XYZ "..."
}
at the top of the library. Library code will be filled with something as C conditional compilation:
@if(MY_FEATURE2)
fun xyz : ...
@fi
It would be ugly and complex but the end user won't see it (unlike in C/C++). All the hard work and complexity would be on library writer only.
Then the user would specify (perhaps in project configuration file):
library foo uses features MY_FEATURE1, XYZ, ABC
and the compiler would preprocess imported libraries and remove all parts that are not needed. Result files will be placed into project directory. Programmer would see only the code he requested, w/o parts he doesn't need and w/o the preprocessor directives.
The import
directive would stay as it is now.
3rd party library may request certain feature to be present, e.g.
import "foo" needs XYZ
and if this library is used by the app then the feature must be also specified by the project.
tests/list.an: 10,5 error: If condition's then expr's type List<'t> does not match the else expr's type List<i32>
if l.next != void* 0 then
^
Type mismatch in the if expression that looks to be caused by failure to bind a generic return type in some contexts.
Do you have a plan to port Ante on Win32? Is there something where I could help? I would try myself, but I read such horror stories about LLVM ...
Could you please write down how do you build the Windows version? I may try to make it working under MSVC. Should this succeed it would allow me to use the debugger and, perhaps get some understanding of the code.
I think there should be an "ante" organization, where this repo is moved and then that the stdlib be moved to its own repo.
The following code snippet:
type Maybe<'t> =
| Some 't
| None
fun div: 't a b -> Maybe<'t>
if b == 0 then None
else Some(a/b)
div 2 4
div 5.0 0.0
(Incorrectly) issues the following error:
u.an: 10,1-3 error: No matching candidates for call to div with args (f64, f64)
...
u.an: 5,5-7 note: Candidate function with params (i32, i32)
...
u.an: 5,5-7 note: Candidate function with params (i32)
In which the second candidate should not exist
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.