Coder Social home page Coder Social logo

orangeduck / cello Goto Github PK

View Code? Open in Web Editor NEW
6.2K 240.0 364.0 2.73 MB

Higher level programming in C

Home Page: http://libcello.org/

License: Other

Makefile 0.74% C 76.71% C++ 3.21% C# 1.03% D 1.66% Go 0.83% Java 2.19% JavaScript 1.68% Lua 6.06% Perl 0.66% Python 1.73% Ruby 1.27% Dart 0.79% R 0.12% Shell 1.32%

cello's Introduction

Cello

Cello is a library that brings higher level programming to C.

By acting as a modern, powerful runtime system Cello makes many things easy that were previously impractical or awkward in C such as:

  • Generic Data Structures
  • Polymorphic Functions
  • Interfaces / Type Classes
  • Constructors / Destructors
  • Optional Garbage Collection
  • Exceptions
  • Reflection

And because Cello works seamlessly alongside standard C you get all the other benefits such as great performance, powerful tooling, and extensive libraries.

Examples

#include "Cello.h"

int main(int argc, char** argv) {

  /* Stack objects are created using "$" */
  var i0 = $(Int, 5);
  var i1 = $(Int, 3);
  var i2 = $(Int, 4);

  /* Heap objects are created using "new" */
  var items = new(Array, Int, i0, i1, i2);
  
  /* Collections can be looped over */
  foreach (item in items) {
    print("Object %$ is of type %$\n",
      item, type_of(item));
  }
  
  /* Heap objects destructed via Garbage Collection */
  return 0;
}
#include "Cello.h"

int main(int argc, char** argv) {
  
  /* Shorthand $ can be used for basic types */
  var prices = new(Table, String, Int);
  set(prices, $S("Apple"),  $I(12)); 
  set(prices, $S("Banana"), $I( 6)); 
  set(prices, $S("Pear"),   $I(55)); 

  /* Tables also support iteration */
  foreach (key in prices) {
    var val = get(prices, key);
    print("Price of %$ is %$\n", key, val);
  }
  
  return 0;
}

Articles

Learning Resources:

Articles about its creation and internal workings:

More Examples

#include "Cello.h"

int main(int argc, char** argv) {

  var items = new(Array, Int, 
    $I( 8), $I( 5), $I(20), 
    $I(15), $I(16), $I(98));

  /* Iterate over indices using "range" */
  foreach (i in range($I(len(items)))) {
    print("Item Range %i is %i\n", i, get(items, i));
  }

  /* Iterate over every other item with "slice" */ 
  foreach (item in slice(items, _, _, $I(2))) {
    print("Item Slice %i\n", item);
  }
  
  return 0;
}
#include "Cello.h"

/* Define a normal C structure */
struct Point {
  float x, y;
};

/* Make it compatible with Cello */
var Point = Cello(Point);

int main(int argc, char** argv) {
  
  /* Create on Stack or Heap */
  var p0 = $(Point, 0.0, 1.0);
  var p1 = new(Point, $(Point, 0.0, 2.0));
  
  /* It can be shown, compared, hashed, etc...
  **
  ** p0: <'Point' At 0x000000000022FC58>
  ** p1: <'Point' At 0x00000000004C7CC8>
  ** cmp: 1
  ** hash: 2849275892l
  */ 
  print("p0: %$\np1: %$\ncmp: %i\nhash: %ul\n",
    p0, p1, $I(cmp(p0, p1)), $I(hash(p0)));
  
  /* And collected by the GC when out of scope */
  return 0;
}

F.A.Q

  • Why does this exist?

I made Cello as a fun experiment to see what C looks like hacked to its limits. As well as being a powerful library and toolkit, it should be interesting to those who want to explore what is possible in C.

  • How does it work?

I recommend reading A Fat Pointer Library to get an overview of how Cello works. You can also peek at the source code, which I'm told is fairly readable, or ask me any questions you like via e-mail.

  • Can it be used in Production?

It might be better to try Cello out on a hobby project first. Cello does aim to be production ready, but because it is a hack it has its fair share of oddities and pitfalls, and if you are working in a team, or to a deadline, there is much better tooling, support and community for languages such as C++.

  • Is anyone using Cello?

People have experimented with it, but there is no high profile project I know of that uses it. Cello is too big and scary a dependency for new C projects if they want to be portable and easy to maintain.

  • Can I get involved?

Yes! That would be great. If you do anything with Cello I'd love to know, you can e-mail me at [email protected], or help with the development at the Cello github repo. Contributions are very welcome.

  • Who are you?

Hello! I'm Daniel Holden. You many know me from a book I wrote or my personal website. I also have a rarely updated twitter account.

cello's People

Contributors

3d0c avatar alexanderdickson avatar andreyvpng avatar awmorgan avatar bcachet avatar codyrioux avatar eddieringle avatar elderica avatar ghedo avatar jart avatar johnlunney avatar jordonbiondo avatar kontinuation avatar lotem avatar ludo6431 avatar mclosson avatar mogui avatar orangeduck avatar radare avatar sakkaku avatar theosotr avatar to1ne avatar tyadav4268 avatar zhangchn 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

cello's Issues

Web Framework

Cello requires a web framework to become popular.

Suggestions:

  • Cello on Chains
  • Cello on Chariots

( No I'm not totally serious :P )

JSON Serialization

Currently, libCello support binary serialization, but it would be great if it supports JSON for parsing and serializing libCello data structures.

Exceptions are not thread-safe

I was just skimming through the code "for the lulz" and noticed this. Consider the following program:

#include "Cello.h"
#include <pthread.h>

local var SomeError = Singleton(SomeError);

local void *some_error(void *argp) {
    puts("in_thread");
    throw(SomeError, "error");
}

int main(int argc, char** argv) {
    pthread_t thread;

    puts("in_main");

    pthread_create(&thread, NULL, some_error, NULL);

    try {
        sleep(1);
    } catch (e in SomeError) {
        puts("in_catch");
    }

    return 0;
}

It prints:

in_main
in_thread
in_catch

meaning that the exception thrown in the separate thread gets caught by the catch in main, in spite of not being wrapped inside the try block, which is, I assume, not the intended behaviour.

Making __exc_active, __exc_depth and __exc_buffers thread-local fixes the problem, i.e. the program prints:

in_main
in_thread

!!  
!!  Uncaught SomeError at (except.c:some_error:9) 
!!  
!!       error
!!  
!!  Stack Trace: 
!!  
!!      [0] ./e() [0x403379]
!!      [1] ./e() [0x40133c]
!!      [2] /lib/x86_64-linux-gnu/libpthread.so.0(+0x7e0e) [0x7f177c6dfe0e]
!!      [3] /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d) [0x7f177c41493d]
!!  

Variable Arguments should only take "var"

The various variable argument functions such as print and catch should be changed such that they only accept var type.

This can be done by switching their type to take var* and using some macro trickery to switch the variable arguments into a literal array declaration ending in Undefined.

A Show Class

I've thought about this in various ways and implementing a "Show" class, essentially a class for converting objects to strings, is really a pain.

First of all issues is memory allocation. We could have objects allocate their own memory for the strings they return. Or have them put their data in some previously allocated block (in which case how big is the block?). Both have downsides but self allocation of memory is perhaps best as although it introduces a "policy" overhead, the fact it adds a performance overhead isn't so important.

Secondly is the fact that I would wish for an Show class to be printf friendly. More specifically I would want it to act like python string formatting. If the string contains a %f then the system automatically attempts to call the "as_double" function upon whichever object it is being passed.

Perhaps the way to solve this is to extract the formatting functionality into a separate body.

Either way, unfortunately I can't see an easy way of doing any of this without basically reimplementing the whole of the printf stack. Ouch.

Benchmarking

Would be good to get some benchmarks to see how the performance compares to other languages. Also good to see what the performance is like for various use cases and what it is strongest at.

Hashtable & Map

Map needs to be finished in implementation.

Both Hashtable and Map need to store duplicates of keys (via "assign") rather than references to keys. Just seems like a more sensible implementation as the user then has to worry less about clearing up memory. Also it seems that it would be hard for the user to delete the keys without causing trouble with iteration and deletion of the actual values later.

src/Exception.c:176:12: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]

Normally I'd submit a PR, but it'd take awhile to get approval, and it's a fairly trivial fix. :)

I'm getting src/Exception.c:176:12: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality] when building libCello on OS X. (GCC details below.)

The offending line is:

  if (var_list_end(vl)) {

which is expanded by the rule

#define var_list_end(vl) (*vl is Undefined)

in to

  if ((*vl == Undefined)) {

Which triggers the -Wparentheses-equality warning which becomes an error.

The fix I found is to simply add -Wno-parentheses-equality to the Makefile CFLAGS (iff using clang for maximum portability.)


❯ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix

make check fails with clang 3.4

clang 3.4 (this is on Ubuntu 13.10 on amd64).

igalic@levix ~/src/libCello (git)-[master] % make check
cc tests/core.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/core.o
cc tests/data.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/data.o
cc tests/exceptions.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/exceptions.o
cc tests/functional.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/functional.o
tests/functional.c:10:32: error: function definition is not allowed here
  var empty_function(var args) { return None; }  
                               ^
tests/functional.c:14:13: error: use of undeclared identifier 'f'
  PT_ASSERT(f);
            ^
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:22:32: error: function definition is not allowed here
  var empty_function(var args) { return None; }  
                               ^
tests/functional.c:26:13: error: use of undeclared identifier 'f'
  PT_ASSERT(f);
            ^
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:27:10: error: use of undeclared identifier 'f'
  delete(f);
         ^
tests/functional.c:36:32: error: function definition is not allowed here
  var empty_function(var args) { return None; }  
                               ^
tests/functional.c:41:38: error: use of undeclared identifier 'empty_function2'; did you mean 'empty_function'?
  var f2 = new(Function, $(Function, empty_function2));
                                     ^~~~~~~~~~~~~~~
                                     empty_function                                                                                                                                               
./include/Cello/Prelude.h:98:37: note: expanded from macro 'lit'
#define lit(T, ...) (T##Data[]){{T, __VA_ARGS__}}
                                    ^
./include/Cello/Prelude.h:146:50: note: expanded from macro 'new'
#define new(type, ...) new_vl(type, var_list_new(__VA_ARGS__))
                                                 ^
./include/Cello/Prelude.h:125:47: note: expanded from macro 'var_list_new'
#define var_list_new(...) var_list_parse(_, ##__VA_ARGS__, Undefined)
                                              ^
./include/Cello/Prelude.h:123:41: note: expanded from macro 'var_list_parse'
#define var_list_parse(_, ...) (var[]){ __VA_ARGS__ }
                                        ^
tests/functional.c:36:7: note: 'empty_function' declared here
  var empty_function(var args) { return None; }  
      ^
tests/functional.c:43:29: error: use of undeclared identifier 'f1'
  PT_ASSERT(((FunctionData*)f1)->func isnt ((FunctionData*)f2)->func);
                            ^
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:45:10: error: use of undeclared identifier 'f1'
  assign(f1, f2);
         ^
tests/functional.c:47:29: error: use of undeclared identifier 'f1'
  PT_ASSERT(((FunctionData*)f1)->func == ((FunctionData*)f2)->func);
                            ^
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:49:10: error: use of undeclared identifier 'f1'
  delete(f1);
         ^
tests/functional.c:59:32: error: function definition is not allowed here
  var empty_function(var args) { return None; }  
                               ^
tests/functional.c:63:17: error: use of undeclared identifier 'f1'
  var f2 = copy(f1);
                ^
tests/functional.c:65:29: error: use of undeclared identifier 'f1'
  PT_ASSERT(((FunctionData*)f1)->func is ((FunctionData*)f2)->func);
                            ^
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:67:10: error: use of undeclared identifier 'f1'
  delete(f1);
         ^
tests/functional.c:78:32: error: function definition is not allowed here
  var empty_function(var args) { return None; }  
                               ^
tests/functional.c:83:34: error: use of undeclared identifier 'empty_function2'; did you mean 'empty_function'?
  var result2 = call($(Function, empty_function2));
                                 ^~~~~~~~~~~~~~~
                                 empty_function
./include/Cello/Prelude.h:98:37: note: expanded from macro 'lit'
#define lit(T, ...) (T##Data[]){{T, __VA_ARGS__}}
                                    ^
./include/Cello/Function.h:13:30: note: expanded from macro 'call'
#define call(x, ...) call_vl(x, var_list_new(__VA_ARGS__))
                             ^
tests/functional.c:36:7: note: 'empty_function' declared here
  var empty_function(var args) { return None; }  
      ^
tests/functional.c:85:13: error: use of undeclared identifier 'result1'; did you mean 'result2'?
  PT_ASSERT(result1 is None);
            ^~~~~~~
            result2
tests/ptest.h:15:46: note: expanded from macro 'PT_ASSERT'
#define PT_ASSERT(expr) pt_assert_run((bool)(expr), #expr, __func__, __FILE__, __LINE__)
                                             ^
tests/functional.c:83:7: note: 'result2' declared here
  var result2 = call($(Function, empty_function2));
      ^
tests/functional.c:102:30: error: function definition is not allowed here
  var asserts_args(var args) {
                             ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [obj/functional.o] Error 1

make check -Werror=trampolines

Was going to run make check. Gotta get back on top of autotools. Where can I disable this specific error in the make step? Is the trampoline error just a warning promoted by -Wall?
gcc -DHAVE_CONFIG_H -I. -I.. -I../tests -std=gnu99 -Wall -Werror -Wextra -Wno-unused -g -O2 -MT tests-functional.o -MD -MP -MF .deps/tests-functional.Tpo -c -o tests-functional.o test -f 'functional.c' || echo './'functional.c
functional.c: In function ‘test_lambda_pipe’:
functional.c:202:1: error: trampoline generated for nested function ‘__LambdaPlus_add_all’ [-Werror=trampolines]

Extensible Type Classes

The advantage of type classes is that they allow for user defined types to work with existing functions.

The disadvantage is that they don't easily allow users to extend existing types to work with new functions (or classes).

In Cello we can provide a way to do the second via some special class field that exists in all Type objects to be called __Parent (there already exists a special field called __Name containing a name string).

By default this field can be set to NULL, but it should be settable to some other value (a Type) at runtime by the user E.G type_parent(Int, IntParent);

The behavior of this field is to act as an extension to an existing type. That is any classes implemented by IntParent will then act as if they were also implemented by Int.

In this way users can register existing types such that they will work with any new type classes they create.

This is not an ideal method as it requires users to write a whole new Parent type and also requires them to add the correct registration at Runtime.

But it is both powerful and flexible and does let the user have some sort of family inheritance for Types if they wish.

Cello + GWAN : Syntax issue

Hi all,

I'm playing a little bit with GWAN + libCello and my code below don't compile properly.

If I don't use libCello it works fine ...

typedef struct
{
  redisContext *rCont;
  redisReply *rReply;
} data_t;

int main(int argc, char *argv[])
{
  data_t **data = (data_t**)get_env(argv, US_SERVER_DATA);
  // Rest of my code ...
}

Here the compiler error:

/csp/cello.c:
In function 'main':
/csp/cello.c:15:12: error: expected identifier or '(' before 'typedef'
   data_t **data = (data_t**)get_env(argv, US_SERVER_DATA);

Any Idea?

Name Change

So the issues with the current name are obvious.

rcdude suggested Coney and Cugar (C-Honey/C-Sugar) which are both pretty good ideas.

Anyone else having a suggestion?

If there is a name change probably also worth while buying a domain and hosting a website/mailing list etc.

Add libCello to Homebrew

I'm not sure if you'd like to add libCello to Homebrew but in case you do I thought I'd lend a hand.

require 'formula'

class Libcello < Formula
  homepage 'http://libcello.org/'
  url 'http://libcello.org/static/libCello-1.0.0.tar.gz'
  sha1 '005466d3dab88bf39e466bd12e9522a80aad617a'

  head 'https://github.com/orangeduck/libCello.git'

  def install
    system "make", "check"
    system "make", "install", "PREFIX=#{prefix}"
  end
end

The formula is currently waiting on changes from issue #24 before it will build successfully.

Functional Tools a Mess

Some of the functional tools such as partial application are a bit of a mess. The fact they rely on essentially pasting arguments (being based off macros) makes them very tricky to use correctly and could result in a lot of unexpected behaviour.

What needs to be created is a Closure object which wraps a function (or a function could be upgraded to this) with proper abilities for partial application - argument reversal - composition etc.

Library Types

A list of potential library types that could still be implemented:

  • Linked List
  • Map
  • Set
  • Generator / Infinite List
  • Regular Expressions
  • Sockets

Library Classes

A list of potential library classes that could still be implemented

* Call - Callable like a function (Could be tied to Function type)

Pull request "Add -fnested-functions to tests_CFLAGS" breaks the tests on 64-bit Ubuntu

#32

This breaks the install on my machine (64-bit Ubuntu on DigitalOcean)

$ make check
Making check in src
make[1]: Entering directory `/home/jpm/libCello/src'
make[1]: Nothing to be done for `check'.
make[1]: Leaving directory `/home/jpm/libCello/src'
Making check in tests
make[1]: Entering directory `/home/jpm/libCello/tests'
make  tests
make[2]: Entering directory `/home/jpm/libCello/tests'
gcc -DHAVE_CONFIG_H -I. -I..  -I../tests  -std=gnu99 -Wall -Werror -Wextra -Wno-unused -fnested-functions -g -O2 -MT tests-core.o -MD -MP -MF .deps/tests-core.Tpo -c -o tests-core.o `test -f 'core.c' || echo './'`core.c
cc1: error: unrecognized command line option â-fnested-functionsâ
make[2]: *** [tests-core.o] Error 1
make[2]: Leaving directory `/home/jpm/libCello/tests'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/home/jpm/libCello/tests'
make: *** [check-recursive] Error 1
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Valgrind ./test find lots of MemoryLeak (in archlinux)

  1. Most of them happened because destruct didn't free the memory it should be. But if I replaced destruct with delete, it worked well. Maybe some places were designed wrong. The delete shouldn't take the place of The destruct.
  2. There are also missing delete in tests/memory.c and tests/data.c. The newand delete should be in pairs.
  3. Only one Leak I can't find how to fix now. About Exception_Throw --> String_Format_To.

Here is my temporary change, [http://pastebin.com/bmDkRpXU], it didn't fix the root cause, but points out where errors place.

Name clash with C++

Hi libCello maintainers,

It is a cool idea to add high-level construct to C language and it will be very useful without a doubt. But it also uses some of the C++ keywords like new, delete, etc. as function names. This will cause problem when building with C++ compilers, for instance.

I guess it is a little bit late to change the names of core functions, but it better happens, the earlier the better. One humble suggestion is to capitalize first character.

Data Structure Improvements

Hashtable / Dictionary

  • Sizes should be prime
  • Should dynamically resize itself
  • Some hashing behaviour could be improved.

Map / Tree

  • Either Implement Red-Black tree or make binary tree re-balance on insertion

CUnit tests?

Hello!

What do you feel about use something like CUnit? (http://cunit.sourceforge.net/)

make test do not show any feedback about test results..

Also.. maybe a coverage tool? (I use --coverage with lcov and genhtml)

If you want, I can set all this to you and send a pull req..

very interesting project.. sorry to bother you with all this :)

Lambda fail

When trying to compile lambda example I get this:

lambdas.c:52:37: error: expected ';' at end of declaration
  var Welcome_Pair(var fst, var snd) {
                                    ^
                                    ;
lambdas.c:57:18: error: use of undeclared identifier 'welcome_uncurried'
  lambda_uncurry(welcome_uncurried, Welcome_Pair, 2);
                 ^
/usr/include/Cello/Lambda.h:61:67: note: expanded from macro 'lambda_uncurry'
#define lambda_uncurry(name, func_ptr, argc) lambda_uncurry##argc(name, func_ptr)
                                                                  ^
/usr/include/Cello/LambdaCurry.h:13:10: note: expanded from macro 'lambda_uncurry2'
  lambda(name, args) { return func_ptr(at(args,0), at(args,1)); }
         ^
/usr/include/Cello/Function.h:48:5: note: expanded from macro 'lambda'
    name->func = ^ var (var args)
    ^
lambdas.c:59:8: error: use of undeclared identifier 'welcome_uncurried'
  call(welcome_uncurried, $(String, "John"), $(String, "David"));
       ^
/usr/include/Cello/Function.h:13:30: note: expanded from macro 'call'
#define call(x, ...) call_vl(x, var_list_new(__VA_ARGS__))
                             ^
3 errors generated.

Which basically means this:

  /*
  ** We can use normal c-functions too.
  ** If they have all argument types as "var".
  ** Then they can be uncurried.
  */

  var Welcome_Pair(var fst, var snd) {
    print("Hello %s and %s!\n", fst, snd);
    return None;
  }

  lambda_uncurry(welcome_uncurried, Welcome_Pair, 2);

  call(welcome_uncurried, $(String, "John"), $(String, "David"));

is not working.

Unable to pass file create test

There is a problem with the test_file_create() on Ubuntu linux, compiled by gcc.

*** glibc detected *** ./tests/test: double free or corruption (!prev): 0x0000000000e0feb0 ***

Looks like problem is here - tests/data.c:1348 - delete(f2)

make check fails on master

igalic@levix ~/src/libCello (git)-[master] % make CC=gcc check
gcc tests/core.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/core.o
gcc tests/data.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/data.o
gcc tests/exceptions.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/exceptions.o
gcc tests/functional.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/functional.o
gcc tests/memory.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/memory.o
gcc tests/ptest.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/ptest.o
gcc tests/test.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/test.o
gcc tests/threading.c -c -I ./include -std=gnu99 -Wall -Werror -Wno-unused -O3 -g -fPIC -o obj/threading.o
gcc obj/core.o obj/data.o obj/exceptions.o obj/functional.o obj/memory.o obj/ptest.o obj/test.o obj/threading.o libCello.a -lpthread -ldl -lm -o test
./test

    +-------------------------------------------+
    | ptest          MicroTesting Magic for C   |
    |                                           |
    | Daniel Holden ([email protected]) |
    +-------------------------------------------+


  ===== Suite Core =====

    | Test Type ... Passed! 
    | Test Cast ... Passed! 
    | Test New ... Passed! 
    | Test Assign ... Passed! 
    | Test Copy ... Passed! 
    | Test Eq ... Passed! 
    | Test Ord ... Passed! 
    | Test Hash ... Passed! 
    | Test Collection ... Passed! 
    | Test Iter ... Passed! 
    | Test Push ... Passed! 
    | Test At ... Passed! 
    | Test Dict ... Passed! 
    | Test As Ctype ... Passed! 
    | Test Stream ... Passed! 
    | Test Type New ... Passed! 
    | Test Type Implements ... Passed! 
    | Test Type Parent ... Failed! 

        1. Segmentation Fault

    | Stopping Execution.
igalic@levix ~/src/libCello (git)-[master] % 

unfortunately, I can't find a core-file, so I can't tell why it's failing

Support for Lambdas on OS X

Nested functions aren't properly supported in Clang it seems - even when compiling to GNU99. To replace them it seems the use of Blocks would be sufficient. Hopefully with some macro use it is possible to provide an identical interface.

http://thirdcog.eu/pwcblocks/

From a brief look over this page seems it would be very difficult to use and implement them via the same interface but I don't have a mac to test on so any contribution to this would be more than welcome.

thread-local storage not supported for this target

I can't build on OS X. I figure it's something machine-specific, as other people are raising issues about post-build problems. That said, I can't figure out what the problem is.

In file included from Array.c:5:
../include/Cello/Exception.h:41: error: thread-local storage not supported for this target
../include/Cello/Exception.h:42: error: thread-local storage not supported for this target
../include/Cello/Exception.h:43: error: thread-local storage not supported for this target

The code:

extern __thread bool __exc_active;
extern __thread int __exc_depth;
extern __thread jmp_buf __exc_buffers[__EXC_MAX_DEPTH];

autoreconf -i suggested ACLOCAL_AMFLAGS=-I m4 in Makefile.am, which didn't help. ./configure; make still results in the build errors above.

gcc -v details:

Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.11~182/src/configure
  --disable-checking
  --enable-werror
  --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2
  --mandir=/share/man
  --enable-languages=c,objc,c++,obj-c++
  --program-prefix=llvm-
  --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/
  --with-slibdir=/usr/lib
  --build=i686-apple-darwin11
  --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.11~182/dst-llvmCore/Developer/usr/local
  --program-prefix=i686-apple-darwin11-
  --host=x86_64-apple-darwin11
  --target=i686-apple-darwin11
  --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

Any ideas? What should I check next?

Name collisions when building inside Xcode 6.2 beta

Hi,

I just tried to embed and build libCello in an Xcode project. Using default build settings, name collision occurred, as Xcode betas are using clang modules to accelerate building, e.g., clear()s from Prelude.h and {SDK ROOT}/usr/include/curses.h collided.

This issue could be circumvented by disabling Modules feature in Build Settings -> Apple LLVM 6.0 - Languages - Modules -> Enable Modules (C and Objective-C).

Want to make Exceptions instances of Show?

When throwing exceptions with a formatted string, printing the exception only prints it's type name.
I believe this is the result of two things:

  1. There aren't any instances of Exceptions, only the types themselves
  2. The formatted string is stored in the current thread struct, not as part of an Exception data struct.

Here's a slightly modified version of libCello's exceptions example:

local var DivideByZeroError = Singleton(DivideByZeroError);

local int try_divide(int x, int y) {
    if (y == 0) {
        throw(DivideByZeroError, "Division By Zero (%i / %i)", $(Int, x), $(Int, y));
    } else {
        return x / y;
    }
}

int main(int argc, char** argv) {

    try {
        int result = try_divide(2, 0);
    } catch (e in DivideByZeroError) {
        print("Uh Oh: %$\n", e);
        return 1;
    }

    return 0;
}

This will print "DivideByZeroError", which is the name of the type, rather than "Division By Zero (2 / 0)".
One option is to use Exception_Message(), but this is internal function that returns the exc_msg of the current thread, and it doesn't make as much a sense as print("%$", e);.

Would it be possible to make Exceptions instances of Show, for example?

Problematic Map_Put() / Map_Get()

It is implied from Map_Get() that the tree in md->root should at the very least be a Binary Search Tree. However the Map_Put() does not seem to respect the restriction that after inserting a new node, the key of any node is greater than any key from left subtree and less than any from right subtree.

And it seems that the Map_Put() would easily lead to degeneration of the tree into a linked list, after a few times of insertions.

Exceptions?

Exceptions can be hacked into native C with relative ease using "setjmp" and "longjmp". The question is ultimately if we want them. The nature of the project would sort of suggest toward them, but some aspects such as the Haskell and C influences would probably shun them in favour of something else. Personally I am not a huge fan.

At the moment on uncountering an error CPlus simply prints an error message to stderr and calls "abort". It seems selfish to not even allow the user a chance to catch this exception without jumping through loops like explicitly checking if a type instances a class or setting an abort signal handler.

Bug in Map_Discard()

In the following code snippet:

void testMap(){
    var m = new(Map);
    put(m, new(String,$(String, "oed")),
        new(Real,$(Real, 20.0)));
    put(m, new(String,$(String, "ci")),
        new(Real,$(Real, 4.0)));
    put(m, new(String,$(String, "cl")),
        new(Real,$(Real, 30.0)));
    put(m, new(String,$(String, "pl")),
        new(Real,$(Real, 7)));
    put(m, new(String,$(String, "od")),
        new(Real,$(Real, 7)));
    put(m, new(String,$(String, "sd")),
        new(Real,$(Real, 7)));
    put(m, new(String,$(String, "osd")),
        new(Real,$(Real, 7)));
    destroyObject(m);
}
void destroyObject(var object)
{
    while (not is_empty(object)) 
    {
        var key = iter_start(object);
        var val = get(object, key);
        discard(object, key);
        delete(val);
        delete(key);
    }
}

When the test procedure is run, the Map_Discard() was called to remove node for key "oed", which happened to be the root node in the node tree, and the Map_Discard() would first call itself to remove the right child with key "od", replacing leaf key and value of root node with the those of deleted child node, and this effectively removed the root node.

By recursively calling itself, Map_Discard() removed the both the keys of the root node ("oed") and the right child ("od") from md->keys and kept the contents of right child in the tree. This introduced an inconsistent state of key list v.s. node tree.

OSX: Extra lib causes build failure for `make check`

Running make check on the recent release (1.1.5) and HEAD fails with:

ld: library not found for -lBlocksRuntime

Removing -lBlocksRuntime from the makefile results in a clean build and all tests passed with both GCC and Clang (i modified the makefile to CC ?= gcc so I could change the compiler).

I don't know how this effects systems running < 10.9. As far as I can tell libBlocksRuntime is included in libSystem as per this document I found via google search.

On systems where -fblocks is supported, specify an additional library path in which libBlocksRuntime can be found. This is not required on Mac OS X, where the Blocks runtime is included in libSystem, but is required on FreeBSD.

The other open issue about OSX, #44 seems to have been resolved at some point and can be closed.

The current formula for libcello in brew is a little outdated (1.1.2 vs 1.1.5) and should be updated once it builds properly.

Make fails under 64-bit Linux

src/String+.c: In function 'String_Eq':
src/String+.c:53:12: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]

Compiling in 32-bit mode seems to fix the problem.

Make fails with the new Xcode command line tools

This is not an actual issue for the library itself; it is more of a heads-up for anyone trying to compile Cello with the new command line tools from Apple.
GCC is not included in Xcode 5 and thus executing gcc points to clang. The problem is that clang does not support nested functions, as nested functions are a gcc extension that is not yet implemented.
The output when you execute make is:
clang: error: argument unused during compilation: '-fnested-functions'
The solution is to install gcc with Macports, Homebrew, etc. and add the line CC = {the command with which the installed gcc is executed} under ifeq ($(findstring Darwin,$(PLATFORM)),Darwin) in the makefile.

This is a multi-platform project, it should respect/ignore line-endings^M

2014 is closing in and files are still the main way to store source-code. Different platforms have different ways of doing that.^M
^M
It would be nice if libCello could ignore those differences.^M
Fortunately git is the most advanced VCS in the world, and can do that!^M
Unfortunately, it does not do it by default.^M
^M
It's so simple to do (which I why it's left as an exercise to the user), in the .gitattribtues file add:^M

text=auto^M

Function Type

It would be nice if there were a way to wrap functions into/as rich data objects.

The main issue is in casting a C function pointer between different and correct types. It seems that some information about the function type is going to have to be stored at runtime.

One solution would be to only allow wrapping of functions in which all arguments are of type "var". We could then store an argument count, and if the function is void, allowing us to do correct casting.

Functions could then be called with an interable or otherwise representing the arguments which could be pulled off and passed to the function.

Alternately we could try to implement a more complicated system using some of the stuff I also use in PyAutoC or LuaAutoC which essentially allow the calling of C functions dynamically and at runtime.

Other Types

Some other potential types and functionality.

  • Regular Expressions
  • Sockets

Sort Doesn't Work

My sort doesn't work. Needs debugging. I've also commented out the test case to hide embarrassment. But I am a little worn out of algorithms for now.

one c file per function

It would be good to split C files into one file per function (statically linked programs will be much smaller).

Modules

It would be great if libcello wrapped libtool's dynamic module system:
http://www.sourceware.org/autobook/autobook/autobook_162.html
http://www.sourceware.org/autobook/autobook/autobook_163.html

Then you could get namespacing for cheap:

with (https in module('https.la')) {
    var options = new(Table, String, String);
        put(options, $(String, "key"),  $(String, "key.pem")); 
        put(options, $(String, "cert"), $(String, "cert.pem"));

    lambda(run_server, args) {
        var response_writeHead = cast(at(args, 0), Function);
        var response_write = cast(at(args, 1), Function);
        call(response_writeHead,
            $(Int,200),
            $(String,"{\"Content-Type\": \"text/plain\"}"));
        call(response_write,
            $(String,"Hello world!")); }
            /* etc */
    }

    call(https, "createServer", options, run_server);
}

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.