GithubHelp home page GithubHelp logo

hirrolot / datatype99 Goto Github PK

View Code? Open in Web Editor NEW
795.0 14.0 17.0 1.29 MB

Algebraic data types for C99

License: MIT License

C 92.51% Shell 2.69% CMake 4.80%
type-system algebraic-data-types c99 sum-types reflection-library introspection variant adt algebraic tagged-unions

datatype99's Introduction

datatype99's People

Contributors

hirrolot 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

datatype99's Issues

datatype and constructor parameter names

Hello,

I use datatype99 in one of my library, like this

datatype(
    Type,
    (C1, p1_1, p1_2, ... p1_n),
    (C2, p2_1, ...)
);

you get the idea :).

In normal struct you give a name to the parameter, this way it is easy to identify the meaning of each parameter.
I can indeeed add after each Constructor a comment describing each parameter.
Now my question ism is it possible to give a name to these parameters or embed a comment directly in the definition of the type.

datatype(
     MyType,
     C1( int@n, double@width, ...)
);

or thomething like this.

thanks for your advices.

Cheers

Frederic

lot's of memory use during compilation

I work on a old computer with only 4 Go of memory.

I am just using two datatype

datatype(
        DetectorType,
        (ImXpadS70, struct imxpad_t),
        (ImXpadS140, struct imxpad_t),
        (XpadFlatCorrected, struct rectangular_t),
        (Eiger1M, struct dectris_t)
        );

datatype(
        detector_t,
        (Detector, const char *, struct shape_t, DetectorType)
        );

since my last update, the amount of memory use during the compilation exploded.
I am wondering if the unroll optimisation is not the culprite ?
It was ok with the code of the 14th of Febuary.

Cheers

Fred

C++ compilation doesn't work

Trying to compile examples/binary_tree.c on C++:

$ g++ examples/binary_tree.c -I. -Iexamples/build/_deps/metalang99-src/include -ftrack-macro-expansion=0
examples/binary_tree.c: In function ‘int sum(const BinaryTree*)’:
examples/binary_tree.c:17:9: error: invalid conversion from ‘void*’ to ‘Leaf_0*’ {aka ‘int*’} [-fpermissive]
   17 |         of(Leaf, x) return *x;
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:17:9: error: invalid conversion from ‘void*’ to ‘Leaf_0*’ {aka ‘int*’} [-fpermissive]
   17 |         of(Leaf, x) return *x;
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘BinaryTree**’ [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘BinaryTree**’ [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘Node_1*’ {aka ‘int*’} [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘Node_1*’ {aka ‘int*’} [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘BinaryTree**’ [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*
examples/binary_tree.c:18:9: error: invalid conversion from ‘void*’ to ‘BinaryTree**’ [-fpermissive]
   18 |         of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
      |         ^~
      |         |
      |         void*

This is caused by Hirrolot/metalang99#25 and was fixed in Metalang99 v1.13.2.

Some suggestions for improvements

This project has great potentials. I have a few practical suggestion for use as an external library:

  1. Use the full '99' names as default, e.g. datatype99 match99, of99 e.g. to avoid name clashes and makes it clear its from the lib.
  2. The compilation is quite slow. Noticeable when using TinyC (https://repo.or.cz/tinycc.git) Use the mob branch. It could be because of all headers are included many times, and causes a lot of IO and file parsing. If this is the case, I suggest the lib only should be used by including metalang99.h, and make sure only one #include per file throughout.
  3. Error: You are using backticks ` somewhere which is not an allowed character. (Error reported by TinyC).
  4. The macro #define expr99(Expr, expr) ((Expr *)(Expr[]){expr}) could maybe be part of the lib.
  5. Consider renaming the project / keyword to sumtype99.

The ast.c example can be easier to read by using infix instead of prefix syntax:

// clang-format off
datatype99 ( Expr,
    (Const, double),
    (Add, Expr *, Expr *),
    (Sub, Expr *, Expr *),
    (Mul, Expr *, Expr *),
    (Div, Expr *, Expr *)
);
// clang-format on

double eval(const Expr *expr) {
    match99 (*expr) {
        of99 (Const, number) return *number;
        of99 (Add, lhs, rhs) return eval(*lhs) + eval(*rhs);
        of99 (Sub, lhs, rhs) return eval(*lhs) - eval(*rhs);
        of99 (Mul, lhs, rhs) return eval(*lhs) * eval(*rhs);
        of99 (Div, lhs, rhs) return eval(*lhs) / eval(*rhs);
    }
    return 0;
}

#define EX(lhs, op, rhs) op(expr99(Expr, lhs), expr99(Expr, rhs))

int main(void) {
    // 53 + (155 / 5) - 113
    Expr expr = EX(Const(53), Add, EX(EX(Const(155), Div, Const(5)), Sub, Const(113)));

    /*
     * Output:
     * -29.000000
     */
    printf("%f\n", eval(&expr));
}

How to export only the tags in a .h

Hello, I have this datatype

datatype(
        Detector,
        (ImXpadS70, struct imxpad_t),
        (ImXpadS140, struct imxpad_t),
        (XpadFlatCorrected, struct rectangular_t),
        (Eiger1M, struct dectris_t)
        );

I do not want to expose all the struct in my API but only the enum with all the choices, in order to hide the implementation behind
only a pointer to Detector.

Is it possible ?

thanks

it seems that datatype doesn not compile with c++

I need to compile some c++ code with some C code.

but it seems that this is not possible.

libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I.. -DPKGDATA=\"/usr/local/share/hkl\" -fpermissive -I.. -I../hkl -I../hkl3d -I../hkl3d/bullet/src -I../third-party/ -ftrack-macro-expansion=0 -I/usr/include/bullet -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -Wall -MT hkl3d.lo -MD -MP -MF .deps/hkl3d.Tpo -c hkl3d.cpp  -fPIC -DPIC -o .libs/hkl3d.o
In file included from ../hkl/hkl-geometry-private.h:27,
                 from hkl3d.cpp:38:
../hkl/hkl-parameter-private.h: In function ‘HklParameterType Parameter()’:
../hkl/hkl-parameter-private.h:39:1: error: ‘ParameterTag’ was not declared in this scope; did you mean ‘Parameter’?
   39 | datatype(
      | ^~~~~~~~
      | Parameter
../hkl/hkl-parameter-private.h:39:1: error: expected primary-expression before ‘)’ token
../hkl/hkl-parameter-private.h:39:9: error: expected ‘)’ before ‘{’ token
   39 | datatype(
      | ~~~~~~~~^
      |         )
../hkl/hkl-parameter-private.h:39:9: error: expected ‘;’ before ‘)’ token
   39 | datatype(
      | ~~~~~~~~^
      |         ;
../hkl/hkl-parameter-private.h:39:1: error: expected primary-expression before ‘)’ token
   39 | datatype(
      | ^~~~~~~~
../hkl/hkl-parameter-private.h: At global scope:
../hkl/hkl-parameter-private.h:39:1: warning: uninitialized ‘const metalang99_semicolon_39’ [-fpermissive]

do I miss something ?

Inconsistent use of diagnostic pragmas (`-Wreturn-type`)

Currently, inside match99, we emit the ... diagnostic push and ... diagnostic ignored "-Wreturn-type" pragmas, but without otherwise99 we won't return to the previous diagnostics state:

DATATYPE99_PRIV_SUPPRESS_W_RETURN_TYPE \

I've spent some time trying to figure out how to automatically resolve this warning but with no success; therefore, the best solution for now is just don't suppress -Wreturn-type but to force a user to suppress it, if necessary.

FYI: The -Wreturn-type warning can be emitted due to the following reasons:

  • A false positive due to the generation of single-step for-loops and the switch statement over a (conceptually) strict enumeration; see this SO question.
  • C enumerations are seen by a compiler as ordinary integers -- see another SO question of mine.

On CMake 3.24.2 DOWNLOAD_EXTRACT_TIMESTAMP warning appears

After upgrading to fresh CMake 3.24.2 I got an unpleasant warning:

CMake Warning (dev) at /usr/share/cmake/Modules/FetchContent.cmake:1267 (message):
  The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy CMP0135 is
  not set.  The policy's OLD behavior will be used.  When using a URL
  download, the timestamps of extracted files should preferably be that of
  the time of extraction, otherwise code that depends on the extracted
  contents might not be rebuilt if the URL changes.  The OLD behavior
  preserves the timestamps from the archive instead, but this is usually not
  what you want.  Update your project to the NEW behavior or specify the
  DOWNLOAD_EXTRACT_TIMESTAMP option with a value of true to avoid this
  robustness issue.
Call Stack (most recent call first):
  build/_deps/datatype99-src/CMakeLists.txt:6 (FetchContent_Declare)
This warning is for project developers.  Use -Wno-dev to suppress it.

Similar issues and PR suggestions are 1 and 2. Consider adding the same fix into the project.

P.S. The same issue is with interface99 and smolrtsp as well

Grammar railroad diagram

With the transformed EBNF shown bellow from the README, we can copy and paste it on https://www.bottlecaps.de/rr/ui in the tab Edit Grammar then switch to the tab View Diagram to see the railroad diagram.

In doing so I noticed that the <arm> nonterminal is not defined.

datatype      ::= "datatype" "(" ( derive_clause "," )? datatype_name ( "," variant )+ ")" 
record        ::= "record" "(" ( derive_clause "," )? record_name ( "," field )* ")" 
datatype_name ::= ident 
record_name   ::= ident 

variant       ::= "(" variant_name ( "," type )* ")" 
field         ::= "(" type "," field_name ")" 
variant_name  ::= ident 
field_name    ::= ident 

derive_clause ::= "derive" "(" deriver_name ( "," deriver_name )* ")" 
deriver_name  ::= ident 

match         ::= "match" "(" lvalue ")" ( arm )+ 
matches       ::= "MATCHES" "(" expr "," ident ")" 
if_let        ::= "ifLet" "(" lvalue "," variant_name "," ident ( "," ident )* ")" stmt 
of            ::= "of" "(" variant_name ( "," ident )* ")" stmt 
otherwise     ::= "otherwise" stmt 

howto deal with unused variables

Hello, I match a constructor but, I do not need all the parameters

        match(detector){
                of(Detector, _, shape, _){
                        *width = shape->width;
                        *height = shape->height;
                }
        }

So when Compiling, I have a lot's of

hkl-binoculars-detectors-2d.c:440:17: warning: unused variable ‘_’ [-Wunused-variable]
  440 |                 of(Detector, _, shape){
      |  

So is there a better solution than switching off the unused-variable in order to silent this message.
Maybe a dedicated _ variable with an unused annotation ?

Cheers

Fred

The `derive` attribute has no postfixed version

The derive attribute is not a macro name -- derive(...) is just a sequence of preprocessor lexemes fed into datatype(...).
It turns out that this is a problem if a user of Datatype99 has a function-like macro named derive somewhere in their code. Even if a user does not specify derive(...) directly, Datatype99 specifies it by itself:

DATATYPE99_PRIV_withDerive_1(derive(dummy), name, __VA_ARGS__)

So I am pretty sure that releasing a new minor version with derive reified into a macro (derive/derive99) would not be a backwards compatibility breakage.

datatype and array

Hello, I would like to define a type like this

datatype(
   Geometry,
   C1(double, double[4]),
   C2(double, double[5]), ...
   );

but it dos not compile,

../../hkl/api2/hkl2.h: In function ‘E4ch’:
../../hkl/api2/hkl2.h:37:1: error: incompatible types when initializing type ‘double’ using type ‘double *’
   37 | datatype(
      | ^~~~~~~~

so my question how can create this type and construct it almost like this

C1(1.0, [1, 2, 3, 4])

thanks for your help.

PS; I am an haskeller, and this is a real pleasure to have a sum type in C thanks to your work :))

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.