Giter Club home page Giter Club logo

ponylang / ponyc Goto Github PK

View Code? Open in Web Editor NEW
5.6K 139.0 410.0 18.87 MB

Pony is an open-source, actor-model, capabilities-secure, high performance programming language

Home Page: http://www.ponylang.io

License: BSD 2-Clause "Simplified" License

C++ 14.88% C 50.58% Makefile 0.31% GAP 0.23% Shell 0.33% Pony 31.86% DTrace 0.13% LLVM 0.01% CMake 0.97% Dockerfile 0.24% PowerShell 0.46%
pony-language pony-source ponyc programming-language actor-model ponylang

ponyc's Introduction

Pony

Pony is an open-source, object-oriented, actor-model, capabilities-secure, high-performance programming language.

Status

Pony is still pre-1.0 and as such, semi-regularly introduces breaking changes. These changes are usually fairly easy to adapt to. Applications written in Pony are currently used in production environments.

Supported platforms

Operating Systems

  • Linux
  • macOS
  • Windows 10

CPUs

  • Full support for 64-bit platforms
    • x86, ARM and RISC-V CPUs only
  • Partial support for 32-bit platforms
    • The arm and armhf architectures are tested via CI (Continuous Integration testing)

Best effort platforms

Best effort platforms mean that there is support for the platform in the codebase but, we don't have any testing for the platform. We won't intentionally break a best-effort platform or remove support for it from the codebase, at the same time, we do make no effort to maintain it. When you go build a "best effort platform" from source, you might find it doesn't build. We welcome thoughtful pull requests to bring the platform up-to-date.

  • DragonFlyBSD (x86 only)
  • FreeBSD (x86 only)

More Information

Resources

Contributing

We welcome contributions to Pony. Please read through CONTRIBUTING.md for details on how to get started.

License

Pony is distributed under the terms of the 2-Clause BSD License. See LICENSE for details.

ponyc's People

Contributors

andymcn avatar aturley avatar chalcolith avatar cquinn avatar darach avatar diltsman avatar dipinhora avatar epiceric avatar ergl avatar fowles avatar georgemarrows avatar jasoncarr0 avatar jemc avatar jonas-l avatar jtfmumm avatar killerswan avatar malthe avatar mfelsche avatar perelandric avatar ponylang-main avatar praetonus avatar rhagenson avatar sblessing avatar seantallen avatar slfritchie avatar srenatus avatar sylvanc avatar theodus avatar tmmcguire avatar winksaville 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  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

ponyc's Issues

Allow nested identifiers in local declarations

Currently, we can do:

var (a, b): (U32, (U32, U32))

But we can't do:

var (a, (b, c)): (U32, (U32, U32))

The second form should be allowed as well. It's already allowed in assignment. While the example above is silly, it can be more useful when doing assignment in conjunction with declaration.

Remove second scope pass

As long as the traits pass is done sensibly (which it should now be) we shouldn't need the second scope pass and can remove it.

I tried to do this a while ago and it caused crashes. A lot of the relevant code has changed since then, so it may now be easy or there may still be stuff that needs fixing.

Prevent names differing only by case

We should allow a type name and non-type name that differ only by case.
We should not allow type names that differ only by case.
We should not allow non-types names that differ only by case.

This means there can be at most 2 names (in any given scope) that differ only by case, one type name and one non-type name.

Should we have lets?

We currently have var and let variables and fields, the only difference being that once setup a let cannot be reassigned to. This gives a small amount of extra type checking, if the programmer chooses to use it.

Is this worth having or should we remove it?

Personally I'm currently thinking no.

Type errors should print the type(s)

Type errors, especially of the form "A is not a subtype of B" should print out what the types invloved are. At the moment only the code location is printed.

Errors for partial functions should be more specific

Consider the following example:

actor Main
  new create(env: Env) =>
    var count: U32 = 10
    var counter: Counter

    if env.args.length() >= 2 then
      count = @atoi[U32](env.args(1))
    end

     ...

The compiler throws the following error message:

function body is partial but the function is not
  new create(env: Env) =>

Whereas the compiler is absolutely right, the error message does not really help much. Instead of just saying that the function body is partial in general, the compiler should say why the function body is partial (namely because of env.args(1), array index).

Type checking arguments on C FFI calls

Amaury raised a good point: if we declared C type signatures in advance, we would get some level of type checking on C FFI calls. The declaration could still be wrong, but it would at least do some checks before runtime.

On the other hand, it's quite nice not to have to "port" a C library to pony (by writing an interface file) in order to use it.

Perhaps we should allow both? A C FFI call that is defined in an interface file is type checked (and doesn't have to specify a return type), but if it's not defined, it's treated as it is currently (any args accepted, return type defined at the call site).

Sort out integer literal typing

We're currently doing the typing of integer literals wrong with regard to signed vs unsigned. For example:
var x:U32
x < 4 - 3
is illegal, because "4 - 3" is signed, but x is unsigned. But:
var x:U32
var t:U32 = 3
x < 4 - t
is legal, because "4 - t" is unsigned.

The question is, what should we be doing?
Should 4 - 3 be signed?
Should we even have signed and unsigned types for integer literals?
Should all integer literals be treated as a signed bit int and converted to the relevant value when we know what type we need?
Can we just use a U128 and convert the value appropriately when we know what we need?
Should we generate an error when the type a literal turns out to actually be causes a loss of precision?
Is this easier if we do top down typing for literals?

Generic "use" prefix handler

Currently the use command can only take file paths. In the future we'd like to take other identifiers, such as URLs.

Create a system to handle strings of the form:
"prefix:path"

Allow arbitrary strings to be registered for prefixes along with handler functions to be called when said prefix is found. Examples:

use "file:foo" - current behaviour, load file foo
use "lib:foo" - cause library foo to be linked to

If no : is found in the use string default to file: (ie current behaviour).

Not sure whether the "as" field should be allowed for arbitrary prefixes. Probably specify at prefix registration whether they are allowed, not or optional.

Update sugar should pass value by name

The update sugar has to pass the rhs from the source as an argument to update(). Currently we pass this as the last positional parameter. Unfortunately this may have complex interactions when combined with optional arguments and named arguments.

The solution to this is to pass the rhs as a named argument, suggest "value". We can't do this until named arguments are implemented of course.

Package dependency loops

With the pass system we now have in place we can trivially allow, or outlaw, package dependency loops. So which do we want to do?

Allowing loops makes ad-hoc development easier, but may lead to messier code.

Outlawing loops forces cleaner code structure, but may lead to massive headaches when making otherwise trivial changes to poorly organised code.

Scheduler should periodically respond() during a behaviour

The runtime should respond() in some calls to the runtime that happen during a behaviour, probably pony_create() and pony_send...(), to allow work generated during the current behaviour to be stolen before the behaviour completes.

Create default constructor if all fields have initializers

The following example does not compile, although all fields within Counter are intialized:

actor Counter
  var _count: U32 = 0

actor Main
  new create(env: Env) =>
    var count: U32 = 10

    if env.args.length() >= 2 then
      count = @atoi[U32](env.args(1))
    end

    var counter = Counter()
main.pony:19:19: couldn't find 'create' in 'Counter'
    var counter = Counter()

We should codegen a default constructor (that does nothing) if all fields of an Actor/class have initializers...

Replace keyword "data"

Currently we use the keyword data to indicate data type definitions. In comments, documentation and error messages I always write "data type" to describe them, because just saying "data" is nonsensical. This is an indication that we're using the wrong keyword, so we should change it. I have no idea what to.

Compare this to the other entities. The keyword class defines a class, the keyword actor defines an actor and so on. But the keyword data does not define a data.

Tabs mess up error reporting

Tabs are counted as single characters by our lexer. This works fine for everything except printing out the indication of where in the line an error occurred. This will go wrong as the source will be printed with tabs in it, which will be expanded to multiple spaces by printf, but the location indication will be printed with space per source character, including one space per tab.

We could simply replace tabs with single spaces when printing out the source for errors.

Alternatively we could replace all tabs with spaces during lexing.

Structural types vs traits

Structural types and traits perform separate tasks but have a huge overlap. As an interface writer I can use entirely traits or entirely structural types or a mix of the 2.

Having 2 very different mechanisms with such an overlap seems like a strange approach.

Can we remove one or other of them completely or merge them into a single mechanism?

Integer division by zero

Given that pony can't crash, how do we handle integer division by zero? Here are the choices:

  1. Raise an error. This means any use of integer division or modulus must come in a try block or in a partial function.
  2. Force the result to zero. So x / 0 or x % 0 results in 0.

I lean towards option 2. Both have the same performance cost (a conditional on the divisor) since catching SIGFPE (or the equivalent on Windows) would be problematic.

Special case parsing errors

Like most parsers we suffer from the problem that parsing errors are pretty much limited to "syntax error". To reduce this problem we should identify common mistakes, slacken the BNF to allow the errors through the parser and then specifically check for those errors.

Split the sugar phase in 2, first the correctness storage, then the sugar phase.

More efficient enum encoding

We can assign enum value types small IDs and then treat them like integer types, (un)boxing as appropriate.

The size of the IDs used should be determined by what the program needs. This requires a full type analysis pass first. Initially we could just say all IDs are 32 bit, but it's questionable whether it's then worth it.

Type checking type parameter capabilities

The following should not type check:

class Foo[A]
  var _x: A

  fun ref set_x(y: A): A => _x = y

To make it work, it should be:

class Foo[A]
  var _x: A

  fun ref set_x(y: A): A => _x = consume y

Type parameters need to be type checked with the lower bound of their possible capabilities.

Specifying a capability for a constraint should give lower bounds as follows:

tag -> iso
box -> trn
val -> val
ref -> ref
trn -> trn
iso -> iso

That lower bound should also be used when determining if a type argument fits its constraint. So:

class Foo[A: Bar val]

...accepts only a Bar val and not a Bar box (exceeds the upper bound) nor a Bar iso (exceeds the lower bound).

Calling to and from C

We need to be able to call in and out of C (and possibly other languages).
Possibly handle primitives automatically, but require the programmer to write a shim to handle comlex types.
Auto-generating object literals is also a possibility.

Default and named formal parameters

We allow default named parameters and specifying which parameter is being provided by name.
Should we allow the same thing for formal parameters?
If so should we require that the constraint and the default for a formal parameter are the same or should we allow them to be specified separately?
The syntax for specifying formal parameters by name could be exactly the same as for specifying value parameters by name.

Support for 128-bit primitive type conversion functions using MSVC

Currently, the Windows build based on MSVC does not support conversion form and to 128-bit signed and unsigned primitive types:

unresolved external symbol __floattisf referenced in function $1_I128_f32
unresolved external symbol __floattidf referenced in function $1_I128_f64
unresolved external symbol __floatuntisf referenced in function $1_U128_f32
unresolved external symbol __floatuntidf referenced in function $1_U128_f64
unresolved external symbol __fixsfti referenced in function $1_F32_i128
unresolved external symbol __fixunssfti referenced in function $1_F32_u128
unresolved external symbol __fixdfti referenced in function $1_F64_i128
unresolved external symbol __fixunsdfti referenced in function $1_F64_u128

As the unresolved symbols are part of libgcc, this shouldn't be an issue with the MinGW-Build.

LLVM compiler-rt provides implementations for these functions, but not for MSVC.

Do we go for platform specific code that we write our own?

Should use "file:foo" commands have guards?

Currently all use commands are allowed to have platform based guards. Should they be outlawed for package usage?

If we don't allow package guards then we can type check for all platforms on every build. However that can also lead to situations where people have to install packages specific to other platforms on their machines.

There are 3 basic options:

  1. Allow guards on package use commands (as now). No-one then ever needs to install any files for any other platforms, but we can't type check all platforms in one go.
  2. Outlaw guards for package use commands (very little work). We can then type check all platforms at once, but people may have to install packages for other platforms, that they will never use. This also leads to the problem that a bug in a package that you will never use can stop your program building.
  3. Something more complex. One possibility would be to allow guards on package uses, try to include the package regardless and not generate errors if a package with a failed condition does not exist.

Options 2 and 3 both also suffer from the potential problem of symbol clash. For example, given this:

  use "windows_foo" where windows
  use "linux_foo" where linux

If both the packages windows_foo and linux_foo define the symbol Bar then there will be a clash, even though the user probably won't expect one.

A further point is that if we allow cross OS compilation up to type checking (which should be easy) then checking another OS type checks OK is as easy as running:
ponyc src/ --pass=expr --target=windows

Error messages: generate as many as we can, make them consistent

All of our error messages should be consistent in terms of capitalisation, spelling, person, tense, etc. At the moment there is some degreee of variation.

We should come up with a standard. The sooner we do this the fewer incorrect messages we'll have to change, but it's really not a high priority.

Capabilities in union types

Capabilities are not encoded at runtime. A union of two types, with differing capabilities, but the same types otherwise, cannot at runtime "determine" what reference was assigned to it.

As a result, when pattern matching, the following should return false, not true:

var x: A ref = A(...)
var y: (A ref | A tag) = x

match y
| var z: A ref => true
else
  false
end

In other words, a union that contains the same "base type" with two different capabilities can only make the weaker guarantee.

Automatic type conversion for arithmetic operations

The following program does not compile, because operands of the multiplications are not of the same arithmetic type.

class Circle
  let _pi: F32 = 3.14
  var _radius: I32

  new create(radius': I32) =>
    _radius = radius'

  fun ref get_radius(): I32 =>
    _radius

  fun ref get_circumference(): F32 =>
    2 * _radius * _pi

  fun ref get_area(): F32 =>
    _radius * _radius * _pi
circle.pony:12:17: left and right side must be the same arithmetic type
    2 * _radius * _pi
                ^

Should we support automatic type conversion, or should Int, Float etc. provide appropriate type conversion functions?

Make parser build ASTs in the right order

Currently the parser macros build the AST backwards and then it is reversed at the end.

The BUILD macros do not work like this, but build the tree in the correct order to start with by keeping a local variable pointing to the last child added and attaching each new child to that.

The parse macros could easily be changed to do this as well. This would not change how ast_add() etc work and so wouldn't impact any other code.

Allow formal parameters on methods

Fun, or possibly not.

Makes the question of what code to generate much more complicated.

Should we allow deduction of method type parameters. Is this actually possible or does it mess up everything?

Errors reported multiple times in used packages

When we use a package that has an error in it we don't correctly record that we have processed that package. If the same package is used again by a different source file we will process it again and print out the error again.

I'll fix this when I work on #6.

Conditional code

We need to allow conditional code, both platform / hardware specific and for debug vs release.

We could switch at the expression, method, type or file level.
We need to provide system / build info (OS, CPU capabilities, debug / release).
Should we also allow programmer configurable info? This could be to allow the aardvark build to be different to the wombat build. It could also be used to make complex decisions based on OS, CPU, etc jsut once, rather than in every file, function, etc.

Error Messages - three questions/requests

I am playing with the type checker, and so I have three questions about error messages

  1. It seems to me that the compiler gives up as soon as it finds the first error message. Is there a flag by which I can ask it to report ALL error messages?

  2. It seems to me that sometimes the same error message is produced twice - as shown below.

=== Building /Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities ===
/Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities/main.pony:20:8: receiver capability must not be iso or trn
fun iso test2a( ) : A tag => // (, TE)
^
can't typecheck package '/Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities'
/Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities/main.pony:20:8: receiver capability must not be iso or trn
fun iso test2a( ) : A tag => // (
, TE)
^
can't typecheck package '/Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities'

Can we avoid that, or do I miss something?

  1. The line number of the error appears with the line saying what the error is, but I think that it would me more helpful next to the erroneous piece of code.
    For example, rather than
    /Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities/main.pony:20:8: receiver capability must not be iso or trn
    fun iso test2a( ) : A tag => // (, TE)
    Have
    /Users/sophiadrossopoulou/Sophia_Research/Pony_Implementation/ponyc/test/capabilities/main.pony -- receiver capability must not be iso or ten
    20:8: fun iso test2a( ) : A tag => // (
    , TE)

Method order restriction

Currently the BNF has the restriction that methods must come in the order constructors, behaviour, functions.

  1. Do we really want this restriction? It's not needed for parsing (unlike the restriction of fields coming before methods).
  2. Since this is in the BNF, if the code violates it we give the unhelpful message "syntax error". Instead the BNF should accept methods in any order and a later pass should enforce the restriction with sensible error messages.

Overhaul AST code

The AST code has evolved a lot from its original form and become messy. It needs a big tidy up, but probably not until we've finished lots of other stuff so the interface becomes more stable.

Remove operator precedence

Operator precedence is bad, it leads to bugs when the programmer and compiler disagree on precedence. However, simply saying all operators are the same precedence doesn't help since programmers can forget that.

The solution we want to use is to force the programmer to use parentheses.

The rule would be that whenever different operators were combined in an expression they would have to be grouped by parentheses. Expressions of the form:
a op1 b op2 c
would only be legal if op1 and op2 were the same operator. But:
a op1 (b op2 c)
would always be OK.

Note that different operators of the same precedence and associativity would still need parentheses, so this would be illegal:
1 + 2 - 3

To implement this the parser would allow any operator sequences, without applying any precedence and keeping parentheses information. The parse fix pass would then check for correctness.

We could leave the parentheses information in the AST, but I think it would be better for the parse fix pass to remove it. Currently this pass does not alter the AST at only, it only checks it. However I think that making it tidy up vestigial tails, only present to allow further checking, is sensible. This would also be useful for other situations, such as function body arrow omission testing.

C -> Pony ABI

For embedding pony libraries in C/C++ applications, we need a C -> Pony ABI. Some open questions are:

  1. At what level do we make things accessible to C? At the actor level, and require the C programmer to craft messages by hand, and send only C types? At a type or even function level?
  2. Do we want an ABI for directly manipulating pony objects? That would also entail GC pinning.
  3. Tuples in pony are ABI compatible with structs in C. Do we want to allow some interaction based on that?

I'm sure there are other open questions as well.

Should sequences be scopes

Every sequence AST node currently is a scope with a symbol table attached. I seem to remember that we decided this wasn't a good idea and should be changed. Am I misremembering, was it simply never done or did we decide against it?

Should match cases use a keyword instead of pipe?

Currently each case in a match is indicated with a pipe symbol, eg:

match _first
| None => _first = ex'
| as ex: Exchange =>
  _first = None
end

It has been suggested that starting lines with a pipe makes it look like the continuation of an expresison on the previous line, especially to those of us used to C. Using a keyword instead may reduce this problem.

match _first
case None => _first = ex' // store this, wait for another submission
case as ex: Exchange =>
  _first = None // reset the stored submission to None
end

Enforce privacy.

Currently, fields and methods starting with an underscore are still publicly visible. Types starting with an underscore are already correctly hidden from importers.

Should all fields be private, regardless of any leading underscore?

Primitive boxing with contravariant traits

Contravariant traits can make it annoyingly tricky to determine when we do or don't need to box primitves. For example, assuming U32 provides Stringable:

class Foo is T
  fun ref bar(x: Stringable)...

trait T
  fun ref bar(x:U32)...

This is allowed due to contravariance.

Since Foo expects any Stringable object, any U32 passed to Foo.bar must be boxed. But T.bar just expects a U32, so that doesn't need to be boxed. This is clearly a problem.

We could say that T.bar picks up the boxing requirement from Foo.bar. However, this means that any other types that provide T will also need to box primitives, even if they can only ever take U32. This will provide a safe system, but will have a potentially huge performance impact.

Possible solutions:

  1. Disallow contravariance with primitive types. Nasty.
  2. T picks up the boxing requirement from Foo (as described above). Potentially a big performance hit.
  3. Do some cunning to determine at runtime whether we need to box. Tricky to see how to do that without a big performance hit.
  4. Come up with a way to make (un)boxing very fast.

String escaping

Are we doing string escaping right?
Should we be doing it at all?
Triple quoted strings can handle including double quotes and newlines, do we need anything else?
Do we need non-printable ASCII or Unicode characters?
Do we have an official way to handle triple quoted strings that want to include a triple quote or end with a double quote?

do we have a definition of Map?

I cannot compile miller/mark_miller.pony.

I changed the "use ... " statement to "use ../../packages/builtin" but it still does not find Map.

Should functions and classes have an end?

All of our control structures terminate with the end keyword (if, while, try, etc). But methods and entities don't. This seems strange and inconsistent to me.

Making methods have a termiantor would also remove the ordering requirement for methods after fields.

Actor Constructor: Arguments must be iso, val or tag

The following code produces a compiler error where it should not. The error thrown is "Constructor arguments must be iso, val or tag".

actor Main
  new create(env: Env)
    Test(this)

actor Test
  var _main: Main

  new create(m: Main)
    _main = m

Allow enum iteration

Since our enums are just unions of primitives we currently have no way to iterate over them.

One possibility would be to provide a mechanism to create an array containing one instance of each union member. All members would have to have a create constructor taking no arguments or it would be a type check error.

type Colours is (Black | Blue | Red | Yellow)

for p in Colours.values() then ...

Colours.values() is sugar for [Black, Blue, Red, Yellow]

Nested tuple access can't parse

Using "dot int literal" to access tuple elements cannot parse correctly for nested elements, because it looks like dot float literal.

Example, access element 2 in element 1 of tuple x:
x.1.2

This is intended to be the lexer tokens:
id x, dot, int literal 1, dot, int literal 2

However it is actually:
id x, dot, float literal 1.2

Possible solutions:

  1. This can be worked around by putting a space anywhere between the 1 and the 2, eg:
    x.1 .2
    but that's pretty ugly.
  2. Handle the dot float access when parsing. This will be really nasty.
  3. Use a different syntax for tuple element access.
  4. Do not allow nested tuples.

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.