Giter VIP home page Giter VIP logo

ccoscope's People

Contributors

rafalcieslak avatar socumbersome avatar

Watchers

 avatar  avatar  avatar

ccoscope's Issues

[type_system branch] Implicit conversion on Proxy VS std::map

As of 01917e4 , when we try to compile it, we get wall of errors:

In file included from /usr/include/c++/4.9/functional:55:0,
                 from /usr/include/c++/4.9/memory:79,
                 from /home/ja/llvm/include/llvm/ADT/SmallVector.h:29,
                 from /home/ja/llvm/include/llvm/ADT/ArrayRef.h:14,
                 from /home/ja/llvm/include/llvm/IR/IRBuilder.h:18,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.h:5,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:1:
/usr/include/c++/4.9/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = ccoscope::Proxy<ccoscope::IntegerTypeAST>; long unsigned int _Idx = 2ul; _Head = ccoscope::Proxy<ccoscope::TypeAST>]’:
/usr/include/c++/4.9/tuple:285:57:   recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = ccoscope::Proxy<ccoscope::IntegerTypeAST>; _UTails = {ccoscope::Proxy<ccoscope::IntegerTypeAST>}; long unsigned int _Idx = 1ul; _Head = ccoscope::Proxy<ccoscope::TypeAST>; _Tail = {ccoscope::Proxy<ccoscope::TypeAST>}]’
/usr/include/c++/4.9/tuple:285:57:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = const char*; _UTails = {ccoscope::Proxy<ccoscope::IntegerTypeAST>, ccoscope::Proxy<ccoscope::IntegerTypeAST>}; long unsigned int _Idx = 0ul; _Head = std::basic_string<char>; _Tail = {ccoscope::Proxy<ccoscope::TypeAST>, ccoscope::Proxy<ccoscope::TypeAST>}]’
/usr/include/c++/4.9/tuple:424:72:   required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(std::tuple<_Args1 ...>&&) [with _UElements = {const char*, ccoscope::Proxy<ccoscope::IntegerTypeAST>, ccoscope::Proxy<ccoscope::IntegerTypeAST>}; <template-parameter-2-2> = void; _Elements = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, ccoscope::Proxy<ccoscope::TypeAST>, ccoscope::Proxy<ccoscope::TypeAST>}]’
/home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:22:72:   required from here
/usr/include/c++/4.9/tuple:142:42: error: call of overloaded ‘Proxy(ccoscope::Proxy<ccoscope::IntegerTypeAST>)’ is ambiguous
  : _M_head_impl(std::forward<_UHead>(__h)) { }
                                          ^
/usr/include/c++/4.9/tuple:142:42: note: candidates are:
In file included from /home/ja/Studies/7sem/cc/project/CCoscope/src/types.h:15:0,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:6,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.h:13,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:1:
/home/ja/Studies/7sem/cc/project/CCoscope/src/proxy.h:24:5: note: ccoscope::Proxy<T>::Proxy(const T*) [with T = ccoscope::TypeAST]
     Proxy(const T* node)
     ^
/home/ja/Studies/7sem/cc/project/CCoscope/src/proxy.h:16:7: note: constexpr ccoscope::Proxy<ccoscope::TypeAST>::Proxy(const ccoscope::Proxy<ccoscope::TypeAST>&)
 class Proxy {
       ^
In file included from /usr/include/c++/4.9/functional:55:0,
                 from /usr/include/c++/4.9/memory:79,
                 from /home/ja/llvm/include/llvm/ADT/SmallVector.h:29,
                 from /home/ja/llvm/include/llvm/ADT/ArrayRef.h:14,
                 from /home/ja/llvm/include/llvm/IR/IRBuilder.h:18,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.h:5,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:1:
/usr/include/c++/4.9/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = ccoscope::Proxy<ccoscope::IntegerTypeAST>; long unsigned int _Idx = 1ul; _Head = ccoscope::Proxy<ccoscope::TypeAST>]’:
/usr/include/c++/4.9/tuple:285:57:   recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = ccoscope::Proxy<ccoscope::IntegerTypeAST>; _UTails = {ccoscope::Proxy<ccoscope::IntegerTypeAST>}; long unsigned int _Idx = 1ul; _Head = ccoscope::Proxy<ccoscope::TypeAST>; _Tail = {ccoscope::Proxy<ccoscope::TypeAST>}]’
/usr/include/c++/4.9/tuple:285:57:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = const char*; _UTails = {ccoscope::Proxy<ccoscope::IntegerTypeAST>, ccoscope::Proxy<ccoscope::IntegerTypeAST>}; long unsigned int _Idx = 0ul; _Head = std::basic_string<char>; _Tail = {ccoscope::Proxy<ccoscope::TypeAST>, ccoscope::Proxy<ccoscope::TypeAST>}]’
/usr/include/c++/4.9/tuple:424:72:   required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(std::tuple<_Args1 ...>&&) [with _UElements = {const char*, ccoscope::Proxy<ccoscope::IntegerTypeAST>, ccoscope::Proxy<ccoscope::IntegerTypeAST>}; <template-parameter-2-2> = void; _Elements = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, ccoscope::Proxy<ccoscope::TypeAST>, ccoscope::Proxy<ccoscope::TypeAST>}]’
/home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:22:72:   required from here
/usr/include/c++/4.9/tuple:142:42: error: call of overloaded ‘Proxy(ccoscope::Proxy<ccoscope::IntegerTypeAST>)’ is ambiguous
  : _M_head_impl(std::forward<_UHead>(__h)) { }
                                          ^
/usr/include/c++/4.9/tuple:142:42: note: candidates are:
In file included from /home/ja/Studies/7sem/cc/project/CCoscope/src/types.h:15:0,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:6,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.h:13,
                 from /home/ja/Studies/7sem/cc/project/CCoscope/src/codegencontext.cpp:1:
/home/ja/Studies/7sem/cc/project/CCoscope/src/proxy.h:24:5: note: ccoscope::Proxy<T>::Proxy(const T*) [with T = ccoscope::TypeAST]
     Proxy(const T* node)
     ^
/home/ja/Studies/7sem/cc/project/CCoscope/src/proxy.h:16:7: note: constexpr ccoscope::Proxy<ccoscope::TypeAST>::Proxy(const ccoscope::Proxy<ccoscope::TypeAST>&)
 class Proxy {
       ^
....................
..................

As I understand, the problem here is that in proxy.h we have template<class U> operator Proxy<U>() and this implicit cast operator causes ambiguity when Type (i.e. Proxy<TypeAST>) is put as a key into std::map. I could remove this operator but then it's a PITA throughout all the rest of the code, because everywhere where we return some type (e.g. FunctionType) and have declared the return type to be Type, we must manually invoke conversion.
How could we eat cake and have cake? Maybe some custom map instead of the one from std::?

Unable to define function in tree.h due to grammar.m

When trying to define any function in tree.h file, e.g. int foo(int x) { return x+1; }, during compilation, we get errors -- in this case, it reads:

CMakeFiles/CCoscope.dir/tokenizer.cpp.o: In function foo(int)': /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: multiple definition offoo(int)'
CMakeFiles/CCoscope.dir/compiler.cpp.o:/home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: first defined here
CMakeFiles/CCoscope.dir/tree.cpp.o: In function foo(int)': /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: multiple definition offoo(int)'
CMakeFiles/CCoscope.dir/compiler.cpp.o:/home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: first defined here
CMakeFiles/CCoscope.dir/lexer.cpp.o: In function foo(int)': /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: multiple definition offoo(int)'
CMakeFiles/CCoscope.dir/compiler.cpp.o:/home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: first defined here
CMakeFiles/CCoscope.dir/token.cpp.o: In function std::iterator_traits<std::_List_const_iterator<int> >::iterator_category std::__iterator_category<std::_List_const_iterator<int> >(std::_List_const_iterator<int> const&)': /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: multiple definition offoo(int)'
CMakeFiles/CCoscope.dir/compiler.cpp.o:/home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: first defined here
CMakeFiles/CCoscope.dir/parser.cpp.o: In function foo(int)': /home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: multiple definition offoo(int)'
CMakeFiles/CCoscope.dir/compiler.cpp.o:/home/ja/Studies/7sem/cc/project/CCoscope/src/tree.h:38: first defined here
CMakeFiles/CCoscope.dir/utils.cpp.o: In function GetTmpFile(std::string)': /home/ja/Studies/7sem/cc/project/CCoscope/src/utils.cpp:19: warning: the use oftmpnam' is dangerous, better use `mkstemp'
collect2: error: ld returned 1 exit status
make[2]: *** [src/CCoscope] Błąd 1
make[1]: *** [src/CMakeFiles/CCoscope.dir/all] Błąd 2
make: *** [all] Błąd 2

Naturally, I don't really need this particular foo function, but it just serves as an example.

Compiler driver

We should support at least these command-line arguments:

  • filename.cco - input file, or a list of input files. .cco files need compiling, .ll files need assembling, .o files need linking.
  • -o - output file name
  • -c - compile & assemble only, no linking.
  • -S - compile only, no assembling. This would emit llvm ir to the output file, and so it would no longer have to be displayed on the standard output.
  • -On - optimisation control. Simple to implement and may be useful for debugging.
  • -l - for passing libs to the linker. This will enable us to implement OpenGL support.
  • -L - lib dirs.

What else could be useful?

Semantics and tests -> interpreter

I have an idea how to kill two birds with one stone.
We will need two things:

  1. At some point, when we add our creative, outstanding features to our language, we should somehow describe semantics of these new things. But writing something like http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf would be a bit tedious :)
  2. To eliminate silly mistakes in code and gain more belief for correctness of our compiler, we would need tests. Maybe some little framework. Current solution of running examples and looking at output is partially satisfactory IMO.

I think that nobody likes doing 1) nor 2). But if we combine them into one thing, namely, interpreter, it should even be fun. Semantics is just describing behaviour and for that the interpreter would be perfect. And we would keep writing examples in .cco, then run them both on the interpreter and our compiled code and automatically compare results.

Does that sound good?

`Complex` type

Refers to typematcher branch.
Implement built-in Complex type, i.e. a thing with double real part and double imaginary part, along with reasonable conversions and operations on it.

Incorrect printing when function call inside?

As of e34675e , when we look at the LLVM's IR our compiler produces on examples/pow.cco, we get

@0 = private unnamed_addr constant [4 x i8] c"%f\0A\00"
@1 = private unnamed_addr constant [4 x i8] c"%f\0A\00"
@2 = private unnamed_addr constant [4 x i8] c"%f\0A\00"
@3 = private unnamed_addr constant [4 x i8] c"%d\0A\00"
@4 = private unnamed_addr constant [4 x i8] c"%d\0A\00"

declare i32 @putchar(i32)

declare i32 @printf(i8*, ...)

declare double @pow(double, double)

define i32 @main() {
entry:
  %c_addr = alloca double
  %b_addr = alloca double
  %a_addr = alloca double
  store double 0.000000e+00, double* %a_addr
  store double 0.000000e+00, double* %b_addr
  store double 0.000000e+00, double* %c_addr
  store double 3.000000e+00, double* %a_addr
  store double 2.000000e+00, double* %b_addr
  %a = load double, double* %a_addr
  %b = load double, double* %b_addr
  %calltmp = call double @pow(double %a, double %b)
  store double %calltmp, double* %c_addr
  %a1 = load double, double* %a_addr
  %calltmp2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), double %a1)
  %b3 = load double, double* %b_addr
  %calltmp4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0), double %b3)
  %c = load double, double* %c_addr
  %calltmp5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @2, i32 0, i32 0), double %c)
  %a6 = load double, double* %a_addr
  %b7 = load double, double* %b_addr
  %calltmp8 = call double @pow(double %a6, double %b7)
  %calltmp9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @3, i32 0, i32 0), double %calltmp8)
  %calltmp10 = call double @pow(double 3.000000e+00, double 2.000000e+00)
  %calltmp11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @4, i32 0, i32 0), double %calltmp10)
  ret i32 0
}

The problem is that the last two calls to printf get the %d format specifier, and as a result those calls print rubbish. This must probably be the issue involving maintype member function in AST class -- which is basically stubbed out, but I believe it should produce correct results in current state of implementation. The ad-hoc solution in CallExprAST::codegen doesn't work unfortunately.

As a side note -- how about throwing away all of our type enums and type classes and use type system that LLVM provides? It should be safer and maybe problems will magically disappear.

Lexer fails on floats/doubles

It seems that something goes wrong when lexing (or parsing?) floating point numbers. On examples/types.cco we get:
Syntax error, unexpected token LITERAL_INT( -4 ), line 7, column 11.
and the number is 3e-4.
Similarly, 3.14 doesn't work either.

compiler.cpp includes codegencontext.cpp

In the header of compiler.cpp:

#include "codegencontext.h"
#include "codegencontext.cpp" // gcc needs it for some reason...

Why exactly is the .cpp file included? That doesn't seem right. In fact, it causes CodegenContext::CodegenContext(...) to be compiled twice, into compiler.o and then codegencontext.o, and thus the linker fails, as there are multiple definitions of that constructor available. Removing that line fixes the issue i.e. the sources compile successfully.

Can we remove that inclusion? Why was it needed in the first place?

`for` loop support

This should be straightforward. You will need to add the for keyword to the lexer grammar, a new class representing for expressions in the AST, a grammar rule that will build the AST node instance when the keyword is spotted, and a codegen rule, which will be similar to if and while statements.

Is `return` a keyword?

I think it would make sense to have return as an enum in KeywordAST instead of having separate ReturnExprAST.
Who doesn't agree? :)

Values in language

We should specify what are values in our language and how they should behave. In particular, specify:

  1. how do we pass arguments (by value, by reference?)
  2. whether we divide values into subgroups, like: primitive and compound (e.g. values of type int versus string) and what it implies for the user

Maybe some other points I forgot to mention?

Runtime library, mix of C and C++

I don't understand what exactly is going on in common/common_types.h -- why are we taking care of whether this unit is compiled by C or C++ compiler when defining struct __cco_complex, and then blissfully use templates below? It seems to me that, because we are using magic from LLVM like TypeBuilder, we are convicted to using C++ only. Is that correct?

Basic types support

At the very least, type system should support:

  • Attaching a type (as we see it) to each value and variable
  • Recognizing types of literals (0, false, 0.0)
  • Recognizing the type of the return value from a function
  • Checking whether argument types for a function call match (no function overloading yet)

Things that may be implemented later:

  • Overloaded operators and resolution
  • Type conversions

Make RTTI available

We use things like typeinfo or dynamic_cast around so we need RTTI enabled. However, when commenting out -fno-rtti in CMakeLists.txt, we get (as of dd59ee5 )

CMakeFiles/CCoscope.dir/codegencontext.cpp.o:(.rodata._ZTIN4llvm8FCmpInstE[_ZTIN4llvm8FCmpInstE]+0x10): undefined reference to `typeinfo for llvm::CmpInst'
CMakeFiles/CCoscope.dir/codegencontext.cpp.o:(.rodata._ZTIN4llvm8ICmpInstE[_ZTIN4llvm8ICmpInstE]+0x10): undefined reference to `typeinfo for llvm::CmpInst'
CMakeFiles/CCoscope.dir/codegencontext.cpp.o:(.rodata._ZTIN4llvm17GetElementPtrInstE[_ZTIN4llvm17GetElementPtrInstE]+0x10): undefined reference to `typeinfo for llvm::Instruction'

I think we need to either pass some additional flags to clang/llvm or rebuild it somehow so that it doesn't complain when using rtti. I don't believe people discard this feature when using llvm -- there must be a way to do that. Question is - how? :)

continue/break statements in loops

To implement this, the GlobalContext would need to store some information about the current loop we're codegenning in. It should be enough to store a pointer to the header block and to the merge block when entering a loop (while/for) codegen and restoring their previous value when returning from it. The break/continue statements would then simply insert a jump to such identified block.

Reorganizing files vs CMake

I thought that having more folders and smaller files would make our project more friendly for maintenance, and a bit more readable -- how do you think?.
At e38753e resides my suggestion. However, CMake is kind of magical for me and I'm having difficulty setting it up properly.

Inserting file location information into the AST

Each node in the AST should know what is the position in the source file that originated the expression associated with the AST. This is necessary for displaying line/column information alongside error messages.

Memory management

We reached a point (at a4bd640 for instance) at which we should decide how our language will manage memory.
So should garbage collector:

Add `String` type support

This comprises of having string literals, working = and + operators overloadings, being able to print strings. And maybe implicit conversions to String.
This will probably entail adding Array type support as well.

float vs double

I think we should decide whether we want float or double datatype in our language -- there is a discrepancy between lexer.lex file and the rest of the compiler.

Colourful output

Colouring the output messages should be simple, and will immediately make our compiler superior to gcc, as it is the only difference most programmers see between gcc and clang.

Scope manager

To make life easier when generating escaping from scopes (e.g. by means of break keyword or ending blocks), it would be nice to have some Scope manager.
Current ad-hoc solution is ugly and the flow should be more or less as follows: open scope -> generate code for block -> close scope, where middle phase could jump to close scope when bumped into break, for instance.
It should also make implementation of invoking destructors (when added :) ) easier.

`print` on `floats` doesn't work

I refer to commit: 2dbb658
On examples/types.cco, when printing f variable, we get 0.0 instead of 3.14159.
I'm not sure whether the root of the problem lays in CallExprAST::codegen or DeclareCFunctions or somewhere else...

Automatic load by conversion not happening?

I encountered a problem at 2377e90 . On examples/complex.cco compilation crashes when codegenning newComplex function (defined in CodegenContext::PrepareStdFunctionPrototypes). As I understand the problem is that there hasn't happened an automatic load. And because I don't fully understand TypeMatcher and conversions related stuff, I'd like to ask for help in nailing down the problem. I most probably screwed up something in ComplexValueAST::Resolve or similar...

`examples/fib.cco` crashes

I think that we may codegen ReturnExprAST incorrectly (or at least that we need to take a closer look at CFG contruction involving return statements).
As of a6c5139 , we produce the following LLVM IR:

define i32 @fib(i32 %n) {
entry:
  %n_addr = alloca i32
  store i32 %n, i32* %n_addr
  %n1 = load i32, i32* %n_addr
  %cmptmp = icmp uge i32 %n1, 0
  %ifcond = icmp ne i1 %cmptmp, false
  br i1 %ifcond, label %then, label %else

then:                                             ; preds = %entry
  %n2 = load i32, i32* %n_addr
  %subtmp = sub i32 %n2, 2
  %calltmp = call i32 @fib(i32 %subtmp)
  %n3 = load i32, i32* %n_addr
  %subtmp4 = sub i32 %n3, 1
  %calltmp5 = call i32 @fib(i32 %subtmp4)
  %addtmp = add i32 %calltmp, %calltmp5
  ret i32 %addtmp
  br label %ifcont

else:                                             ; preds = %entry
  ret i32 0
  br label %ifcont

ifcont:                                           ; preds = %else, %then
  ret i32 0
}

and it seems like it falls into infinite loop. But I'm not sure.

And as a comparison, that's what clang outputs on an equivalent fib.cpp program with -O0:

define i32 @_Z3fibi(i32 %n) #0 {
entry:
  %retval = alloca i32, align 4
  %n.addr = alloca i32, align 4
  store i32 %n, i32* %n.addr, align 4
  %0 = load i32, i32* %n.addr, align 4
  %cmp = icmp sle i32 %0, 0
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %1 = load i32, i32* %n.addr, align 4
  %sub = sub nsw i32 %1, 2
  %call = call i32 @_Z3fibi(i32 %sub)
  %2 = load i32, i32* %n.addr, align 4
  %sub1 = sub nsw i32 %2, 1
  %call2 = call i32 @_Z3fibi(i32 %sub1)
  %add = add nsw i32 %call, %call2
  store i32 %add, i32* %retval, align 4
  br label %return

if.else:                                          ; preds = %entry
  store i32 0, i32* %retval, align 4
  br label %return

return:                                           ; preds = %if.else, %if.then
  %3 = load i32, i32* %retval, align 4
  ret i32 %3
}

We can see that it's smart to have one ret -- something we should try to achieve probably.

Variables' occurences and scoping

We should add the ability for the user to:

  • declare variables (almost) anywhere (not just at the beginning of a block)
  • declare variables with the same name as long as they are in different blocks (scopes)
  • alongside with the previous point, maybe some scope resolution operator (like :: from C) -> but this may come as another task if turns out to be difficult

Linking vs standard library of non-C functions

As of a34d6cd , I broke the gcd example, because when we try to compile and link examples/gcd.cco and examples/gcd_main.cco, we have multiple definitions of newComplex functions (which I consider a standard-library function for our compiler, but it's not as low level as things in libcco to put it there). The problem is that I create this function in CodegenContext::PrepareStdFunctionPrototypes and, well, when we compile more than one file, multiple definitions will certainly appear.
The question is: what would be the best place to put this creation of newComplex? It seems to me that during compilation of "normal" files, we should emit just the prototype (in each of them), and then build a file with all the standard functions (currently only newComplex but I think there will be more in the future?) codegenned there, and link all those files up.
Do you agree?

And a kind of related question -- why can't we emit IR code when we compile more than one file? I hope it's just an artificial obstacle, because if we decide to have this standard library, then we will always link at least two files and it shouldn't hinder us from peeking at IR.

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.