Giter VIP home page Giter VIP logo

c2compiler's Introduction

C2Compiler

Please see C2Lang.org for more info about C2!

The C2 project attempts to create a new language, strongly based on C. In a nutshell, the main differences with C are:

  • no more header files (too much typing)
  • no includes
  • packages (needed if we can't have includes)
  • compiled per target (not per file)
  • more logical keywords (public/local replaces static)
  • integrated build system

Below are the instructions for building and using the C2Compiler.

Have fun! (and code..)

Generic

C2 is based on LLVM 7.0 and some parts of Clang 7.0. The design of C2C's Parser and ASTBuilder classes are heavily based on clang's Parser and Sema class, so hereby my thanks to the Clang folks!

What needs to be done

A short list of open items (the full list would probably fill-up GitHub) with their priority:

  • [high] c2c: parse full syntax into AST (ALMOST DONE)
  • [high] c2c: generate IR code for more AST elements
  • [medium] tool: create graphical refactor tool (c2reto) (IN PROGRESS)
  • [medium] c2c: tab completion on targets in recipe / cmdline args
  • [medium] tool: create c-parser for parsing C headers.
  • [medium] tool: create c2format - astyle for C2.
  • [low] tool: c2grep - grep only files in recipe

Installation

Read the installation document for installation on Linux or OSX. For Windows installation, see windows installation document.

Using the C2 compiler

By default, c2c will only parse and analyse the targets. Generating C-code should work on all examples, but generating LLVM's IR code is work in progress. In the examples directory: (or add -d examples/)

c2c multi
c2c hello
c2c puzzle
c2c -I working_ir

It's also possible to manually compile a single .c2 file without a recipe file with:

c2c -f <file.c2>

To generate ANSI-C code, use:

c2c -C <target>

The C2 compiler is able to generate a package dependency file in dot format. This file can be converted into a png as follows:

c2c --deps <target>
dot -T png output/target/deps.dot > image.png

To see all available options, run:

c2c -h

c2tags

c2tags is C2's version of ctags. This tool is used by vim (e.a.) to "jump to definition". See the installation document on how to install.

How it works is as follows:

  • use --refs or add $refs in recipe.txt to generate refs file during compilation.
  • c2c generates a refs file per target. This file contains all references and their respective destinations.
  • c2tags currently doesn't have a full-blown vim-plugin yet, but a small code-fragment in your .vimrc should suffice.
  • Pressing ctrl-h (configurable) with your cursor on any symbol will jump to its definition. Pressing ctrl-o (default) will jump back.

Just like c2c itself, c2tags can be called from any (sub)directory in the project tree.

c2compiler's People

Contributors

apg360 avatar bryant1410 avatar bvdberg avatar dandigit avatar dersaidin avatar lerno avatar luciusmagn avatar paulie-g avatar vfr-nl 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c2compiler's Issues

Update cast syntax

Update cast syntax to one of the suggestions in the forum, in my opinion it does not really matter which one - but let’s have it fixed.

vala has closures, please add them too

Hello, I looked over the slides, looks good so far and since it is already somewhat working, double props.
I would like you to look into adding closures.
This is like the only thing in C which makes me a little bit mad.

Incorrect cast behaviour in LiteralAnalyser

  1. cast(3) => will cast the expression to a 31 bit integer.
  2. cast(2147483648) => 0
  3. cast(2147483647) => -1
  4. cast(1073741823) = 1073741823
  5. cast(1073741824) = -1073741824

The cast is using getIntegerWidth to set the resulting width, causing this issue.

Compiler crash on parsing expression

Trace:
Assertion failed: (BitWidth == RHS.BitWidth && "Bit widths must be the same"), function operator+=, file /Users/lerno/llvm/lib/Support/APInt.cpp, line 193.

This is the expression that triggers the crash:

i32 a = ((1 << 2) + 3);

Decide if the parser should use naming rules.

I suggest that the parser should use the naming rules in order to simplify parsing and analysis. This would make C2 parsing context free and also speed up parsing.

A suggested ”out” for calling C or exporting to C is to make C be transformed to in linkers and external C interfaces. c can be used for anything that ”should” start with a lowercase letter. Again, this is stripped in external C gen.

Clean up literal parsing

Literal parsing currently has vestiges of Clang C parsing. Remove those according to the simplified requirements of C2 (only maxfloat type / bigint)

hello world error during external c compilation

When trying out the hello world example, I am getting an external c compilation error. After building the c2compiler, all the tests seem to be fine:

...
RESULTS: 603 tests (583 ok, 0 failed, 20 skipped) ran in 14393 ms
[100%] Built target tests

Here is the .c2 file:

module hello;

import stdio as io;

public func i32 main(i32 argc, char*[] argv) {
    io.printf("Hello C2!\n");
    return 0;
}

And the recipe:

executable hello
  $warnings no-unused
  $generate-c
  hello.c2
end

Here is the tree of the resulting output:
screen shot 2018-02-03 at 2 09 53 pm

Here is the results of gcc --version:

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin17.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Any thoughts on where I should look into this one?

We need a list of AST parses that fail.

In order to follow up the remaining parts of the syntax that doesn't properly parse to C, we need a list of what's missing. Such a list could be kept in the wiki initially if filing issues is problematic. It's reasonable to focus on getting the language to work completely for basic things like all literals, pointers etc.

Struct methods

Being able to define functions on structs is quite useful and common

Calculate struct sizes and offsets

In pull req #79, pointers and built ins are correctly sized, however size for structs are not. Implement the correct sizes for packed and regular structs.

Also, it's not clear what @(packed) means in the context. Is it only that fields are aligned different from the default, or can fields be reordered?

If only the former, should we consider struct reordering (shuffling the order of fields in an optimal way for alignment)? Should it even be default, with a special attribute to prevent reordering (this is Zig's approach)?

I suggest this is added to milestone 2.

c2c unable to compile on Ubuntu

Error messages:

Linking CXX executable c2c
libc2core.a(C2Builder.cpp.o): In function C2::C2Builder::build()': /home/user/llvm_build/c2compiler/c2c/Builder/C2Builder.cpp:(.text._ZN2C29C2Builder5buildEv+0x5a4): undefined reference tollvm::sys::getDefaultTargetTriple()'
libc2core.a(C2Parser.cpp.o): In function C2::C2Parser::ParseVarDef(bool)': /home/user/llvm_build/c2compiler/c2c/Parser/C2Parser.cpp:(.text._ZN2C28C2Parser11ParseVarDefEb+0x213): undefined reference toclang::Lexer::getSpelling(clang::Token const&, clang::SourceManager const&, clang::LangOptions const&, bool_)'
libc2core.a(C2Parser.cpp.o): In function C2::C2Parser::ExpectAndConsumeSemi(unsigned int)': /home/user/llvm_build/c2compiler/c2c/Parser/C2Parser.cpp:(.text._ZN2C28C2Parser20ExpectAndConsumeSemiEj+0x165): undefined reference toclang::Lexer::getSpelling(clang::Token const&, clang::SourceManager const&, clang::LangOptions const&, bool_)'
libc2core.a(C2Parser.cpp.o): In function C2::C2Parser::ParseInitValues()': /home/user/llvm_build/c2compiler/c2c/Parser/C2Parser.cpp:(.text._ZN2C28C2Parser15ParseInitValuesEv+0x2ae): undefined reference toclang::Lexer::getSpelling(clang::Token const&, clang::SourceManager const&, clang::LangOptions const&, bool_)'
libc2core.a(FileAnalyser.cpp.o): In function C2::FileAnalyser::resolveEnumConstants()': /home/user/llvm_build/c2compiler/c2c/Analyser/FileAnalyser.cpp:(.text._ZN2C212FileAnalyser20resolveEnumConstantsEv+0x3ee): undefined reference tollvm::APInt::toString(unsigned int, bool) const'
libc2core.a(FunctionAnalyser.cpp.o): In function C2::FunctionAnalyser::analyseDesignatorInitExpr(C2::Expr_, C2::QualType)': /home/user/llvm_build/c2compiler/c2c/Analyser/FunctionAnalyser.cpp:(.text._ZN2C216FunctionAnalyser25analyseDesignatorInitExprEPNS_4ExprENS_8QualTypeE+0x496): undefined reference to llvm::APInt::toString(unsigned int, bool) const'
libc2core.a(FunctionAnalyser.cpp.o): In functionC2::FunctionAnalyser::checkArrayDesignators(C2::InitListExpr_, long_)': /home/user/llvm_build/c2compiler/c2c/Analyser/FunctionAnalyser.cpp:(.text._ZN2C216FunctionAnalyser21checkArrayDesignatorsEPNS_12InitListExprEPl+0x6d4): undefined reference to llvm::APInt::toString(unsigned int, bool) const'
libc2core.a(FunctionAnalyser.cpp.o): In functionC2::FunctionAnalyser::analyseBitOffsetIndex(C2::Expr_, llvm::APSInt_, C2::BuiltinType_)': /home/user/llvm_build/c2compiler/c2c/Analyser/FunctionAnalyser.cpp:(.text._ZN2C216FunctionAnalyser21analyseBitOffsetIndexEPNS_4ExprEPN4llvm6APSIntEPNS_11BuiltinTypeE+0x2fa): undefined reference to llvm::APInt::toString(unsigned int, bool) const'
/home/user/llvm_build/c2compiler/c2c/Analyser/FunctionAnalyser.cpp:(.text.ZN2C216FunctionAnalyser21analyseBitOffsetIndexEPNS_4ExprEPN4llvm6APSIntEPNS_11BuiltinTypeE+0x50a): undefined reference to`llvm::APInt::toString(unsigned int, bool) const'
clang-3.7: error: linker command failed with exit code 1 (use -v to see invocation)
CMakeFiles/c2c.dir/build.make:86: recipe for target 'c2c' failed
make[2]: *
* [c2c] Error 1
CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/c2c.dir/all' failed
make[1]: *** [CMakeFiles/c2c.dir/all] Error 2
Makefile:75: recipe for target 'all' failed
make: *** [all] Error 2

compare and contrast

hi, this reminds me of my pet language project (long since ditched, but it demonstrates the kind of features I want)
could you comment on what features you overlap with or could absorb? https://github.com/dobkeratops/compiler

I dont mind what syntax is used; I just copied rusts syntax as closely as possible to reuse it's existing syntax highlighters

Organize compiler development into milestones

In order to get some structure into development, please organize the project into milestones (can be simple ordering like 1, 2, 3 and so on). In each milestone we gather a bunch of features that should be completed before we go into the later additions.

Unclear semantics of integer and float constants

There are basically two possible approaches for C2:

  1. Distinguish between integer types, so that an integer constant may have a specific bit width. In order to affect this we must explicitly either cast or have suffixes 1.0f, 10uL etc.
  2. Say that integer constants are handled as BigInts (we already borrow that functionality from llvm), and that floating point are always folded as highest available precision (f128 or f64). At the final step, it is then rounded to the correct precision / size.

For the second alternative, if we have the following code:

i32 a = 2 * 1000;
f32 b = 2 * 1000.0;
i8 c = 3;
i32 d = 600 + a + 10000 * c

Expressing the above in C++:

int32_t a = (BigInt(2) + BigInt(1000)).toSigned32();
float b = (float)(2.0 * 1000.0);
i8 c = 3;
i32 d = 600 + a + 10000 * (i32)c;

An overflow, for example:

i8 a = 2 * 127;
u8 b = 255 + 1;

Would be detected and flagged as error at runtime.

However, this would not be flagged:

i8 b = 2;
i8 a = b * 127;

Nor would this:

i8 a;
....
u16 b = 65535 + a + 65535;

Only directly folded constants have the error.

I think we should go for (2), since tagging constants with suffixes is a drag and create those incredibly annoying errors when you turn on strict type checking.

Implement Plan 9 C style structure displays.

http://doc.cat-v.org/plan_9/4th_edition/papers/comp

From the document above

The compiler has several extensions to ANSI C, all of which are used extensively in the system source. First, structure displays permit struct expressions to be formed dynamically. Given these declarations:

typedef struct Point Point;
typedef struct Rectangle Rectangle;

struct Point {
  int x, y;
};

struct Rectangle {
  Point min, max;
};

Point p, q, add(Point, Point);
Rectangle r;
int x, y;

this assignment may appear anywhere an assignment is legal:

r = (Rectangle){add(p, q), (Point){x, y+3}};

The syntax is the same as for initializing a structure but with a leading cast.

If an anonymous structure or union is declared within another structure or union, the members of the internal structure or union are addressable without prefix in the outer structure. This feature eliminates the clumsy naming of nested structures and, particularly, unions. For example, after these declarations,

struct Lock {
  int locked;
};

struct Node {
  int type;
  union {
      double  dval;
      double  fval;
      long    lval;
  };      /* anonymous union */
  struct Lock;    /* anonymous structure */
} *node;

void    lock(struct Lock*);

one may refer to node->type, node->dval, node->fval, node->lval, and node->locked. Moreover, the address of a struct Node may be used without a cast anywhere that the address of a struct Lock is used, such as in argument lists. The compiler automatically promotes the type and adjusts the address. Thus one may invoke

lock(node).

Anonymous structures and unions may be accessed by type name if (and only if) they are declared using a typedef name. For example, using the above declaration for Point, one may declare
struct {
int type;
Point;
} p;

and refer to p.Point.

The most important change here is the type promotion / adjustment.

That is: lock(node) is interpreted as lock(&(node->Lock)). The solution does not have to look exactly like the Plan 9 one, in particular, one might want to change the anonymous syntax somewhat, since the lack of balance in layout is a bit jarring.

Either of the following

struct {
  int type;
  Point @(inline);
} p;

struct {
  int type;
  Point point @(inline);
} p;

Could be alternatives for the same functionality.

Test Parser/sizeof_expr_ok fails

The test has this:

i32 a = sizeof(i32*)
i32 c = sizeof(a*);

This fails (correctly) since a is not a type (sizeof(i32*) succeeds as expected). However, one might have expected this to be a typo, where we wanted &a instead of a*. Sadly sizeof(&a) does not seem to work.

Also, there's a very valid case of this code:

i32* x = nil;
i32 y = sizeof(x*);

This does not work either. In the &a case, '&' is probably incorrectly parsed by C2Parser::ParseSizeof, but the * case is more complex. Obviously we can't do a simple "replace x by its type" when resolving types, because that would allow the analyser to happily parse x* a = 23 as equal to i32 a = 32!

Unfortunately I don't know the code sufficiently well to offer a fix that I'm comfortable with.

sub-struct initialization fails

The analysis pass of the following code fails:

type T struct {
    i32 i;
    union {
        u32 u;
        void* p;
    }
}

T t1 = { 10, .u=20 }     // error: field designator 'u' does not refer to any field in type '(struct)T'

Mixing designated initializers with non-designated ones seems to be allowed in C for substructs.
The Analyzer also needs to search sub-structs/unions and keep track of what's initialized as well

Suggestion: Rename char to byte

One of the flawed type names you’ve skipped renaming is char. Char implies that it contains a character, but in this era of multibyte character encoding formats the name doesn’t really describe something that can hold a character. Languages like C# have renamed C’s char to byte, and supplied a new char that is capable of containing a 16bit Unicode codepoint.

I believe that any successor to C needs to correct the byte / char / mbcs issue. Preferably in a manner that eliminates ambiguity for byte and leans towards UTF-8 support.

Love the project, great work so far.

Decide on compile time function prefix or not.

I've raised this in the forum and it needs some resolution I think as it affects syntax and parsing quite a bit:

Currently compile time functions, such as sizeof has no prefix. I've always found sizeof a bit confusing since it clearly looks like a normal function but isn't. Now, if we add semantic macros and more compile time functionality, it seems like we should not pollute the global namespace with a huge amount of keywords. Consequently I'd like a separate namespace for macros, and I suggest those start with "@".

Consequently it's @sizeof, @typeof etc. Semantic macros would then share the same namespace so @my_macro(....) when expanding a macro. Where the "@" should be thought of as "macro expansion starts here"

Alternatively we use "#" or even "$", but for # it's more associated with line based macro handling, so it might feel weird and confusing:

i32 foo = #sizeof(a);
i32 foo = @sizeof(a);

There also needs to be a guideline when to use the prefix. For example, consider a defer that is possible to write inline:

Foo *foo = malloc(@sizeof(Foo));
defer free(foo);

Foo *foo @defer(free) = malloc(@sizeof(Foo)); // Same meaning as above.

Foo *foo = malloc(@sizeof(Foo)) @defer(free); 
// Actually same as
void  *__temp;
Foo *foo = __temp = malloc(@sizeof(Foo)); 
defer free(__temp);

Here defer both would act as a keyword and as an attribute macro.

Using @ttributes and keywords, the examples would look like this I suppose:

Foo *foo = malloc(sizeof(Foo));
defer free(foo);
Foo *foo @(defer=free) = malloc(sizeof(Foo));
Foo *foo = malloc(sizeof(Foo)) @(defer=free); 

I'd like to be able to separate attributes that work like compiler directives from constructs that work like actual macros, transforming the actual meaning of the code. That's why I prefer the former version.

Note that the above does not need to be decided right away. For the current state of C2, the only thing that needs a decision is really whether sizeof should have a @ prefix or not, and if this keyword should be common to all compile time functions.

c2c: error: cannot find library 'libc'

Hey everyone,

I love the project. I have a dumb question: after going through the setup and attempting to compile the hello world example, I am getting the following:

building target hello
c2c: error: cannot find library 'libc'

In my .zshrc I have the following:

export C2_LIBDIR=/Users/youngtodd/c2compiler
alias c2c=/Users/youngtodd/c2compiler/build/c2c/c2c
export CC=clang
export CXX=clang++
export PATH=$HOME/llvm-c2/bin:$PATH

I am sure I am doing something dumb here. Do I just need to append to my $PATH to point to libc here?

Decide, document and implement identifier max lengths

Right now, names for identifiers etc are (as far as I can tell) arbitrarily long. That might be fine right now, but it can create problems further down the line, when trying to allocate things statically. Besides, I would also say that arbitrarily long identifiers aren't a good idea anyway.

C99 has a 31 characters (internal 63), Java has 65535(!).

The advantage of a lower limit is hashing and memory usage. Any power of two up to 255 feels reasonable. Maybe 63 or 127?

ARatherLongNameForThisStructIs31 foo;
IfWeGoFor63CharactersThenAStructCanBeJustAsLongAsThisOneHere12 bar;

This max length is excluding the module namespace though!

Missing debugging code in IR generation for LLVM

Clang emits various debugging pointers which helps debugging the code. Since the code generation is already based on Clang, we should probably add this to C2's code generation as well.

Following Clang closer in the code gen will also help in quickly getting solid IR out. (Unless we get som contributor who is an LLVM expert)

Wiki is locked

Could perhaps we open the wiki for documentation collaboration again?

Add a license to the project

It's possible to add a general license for the project (directly from GitHub), as well as other things (code of conduct etc). I suggest that this is added.

[Feature] Function annotations?

in C++ you can write const int func() {} (outside of classes has little effect however) and in C with GCC extensions you have __attribute((pure))__ __attribute((const))__ int func() {} (docs)

In C2 it's not necessary to implement code analysis and optimisation at this point, but it would be nice if these were added to the C2 grammar as no-ops, so that they can be made useful in the future when the compiler has matured into something worth writing optimisation algorithms for (or borrowing from GCC).

This way we can tell C2 and LLVM that the pure function should have memoised return value (same output for given inputs), and that a const function is pure but may not access any global memory, or similar semantics.

"Adopt" llvm classes to reduce compile time dependency on external packages

C2 uses a handful of LLVM classes outside of IR generation. One of those is the APInt class.

My suggestion is that these classes be copied into the C2 repo under a different namespace (and possibly also name). This allows us to strip the class to what we use and releases us from internal dependencies on LLVMs quickly changing codebase.

Compiler warnings

warning: unknown warning option '-Wno-maybe-uninitialized'; did you mean
'-Wno-uninitialized'? [-Wunknown-warning-option]

unary + is not pruned from AST.

There is no need to leave the unary + in the AST, this just makes analysis a bit more difficult. Either prune it in the lexer (when doing the lexer) or prune it in the AST during parsing.

LLVM IR not generated (c2c crash) in certain use-case

Using version f8fe89b

recipe.txt

executable simple
    $warnings no-unused
    $generate-ir
    simple.c2
end

simple.c2

module simple;

public func int32 main(int32 argc, int8*[] argv) {
        char *str = nil;
        return 0;
}

command and output

$ c2c -I
building target simple
NilExpr


Command terminated

Naming conventions for "private" struct members.

I was looking at this: https://github.com/c2hub/c2vector/blob/master/c2vector/c2vector.c2

And realized that maybe C2 needs a convention (or a way) to name / signal "internal" (I wouldn't use 'private') fields.

There are a few options:

  1. Name convention: "_foo" – Dart does this, and they actually skip "private/public" by saying anything with "_" is private.
  2. Keyword: "private foo" / "internal foo" / "local foo" in the struct declaration together with have to use some special way to get hold of it. In the case of c2vector2: c = v.capacity and maybe a = v.$total or c = (private v).total or c = private v.total (not beautiful solutions, just describing the options we have)
  3. Sigil: e.g. "$foo" like in type Foo struct { int $foo; }

Implement C99 sparse array initialization

In C99-compiler, it is possible to initialize a sparse array with the following syntax:

char* foo[10000] = { [42] = "The Meaning", [13] = "Bad luck", [1999] = "Party like it's" };

// foo[22] => NULL
// foo[13] => "Bad luck"

Completely remove dependency on Clang's lexer

  1. The lexer parses a lot of stuff that C2 shouldn't, this makes the code rather unclear at places.
  2. The lexer has a firm idea about how to lex certain tokens, like "@" which might complicate parsing.
  3. We have full C pre-processing. I don't think this is a good thing.
  4. Keywords need to be defined in the Clang source :-[
  5. Code requires reading up on a lot of Clang code to see how things work, rather than just the c2compiler code.

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.