Giter Site home page Giter Site logo

Comments (17)

cblp avatar cblp commented on August 29, 2024

suggested test

diff --git a/tests/unit/Main.hs b/tests/unit/Main.hs
index ff735fb..3788a5d 100644
--- a/tests/unit/Main.hs
+++ b/tests/unit/Main.hs
@@ -150,6 +150,7 @@ cQuotationTests = testGroup "C quotations"
     , testCase "block items antiquote" test_item
     , testCase "qualifier with type antiquote 1" test_qual_antitype1
     , testCase "qualifier with type antiquote 2" test_qual_antitype2
+    , testCase "qualifier with type antiquote 3" test_qual_antitype3
     ]
   where
     test_id :: Assertion
@@ -330,6 +331,13 @@ cQuotationTests = testGroup "C quotations"
       where
         tau = [cty|int|]
 
+    test_qual_antitype3 :: Assertion
+    test_qual_antitype3 =
+        [cexp|(const $ty:tau) NULL|]
+          @?= [cexp|(int * const) NULL|]
+      where
+        tau = [cty|int *|]
+
 cPatternAntiquotationTests :: Test
 cPatternAntiquotationTests = testGroup "C pattern antiquotations"
     [ testCase "arguments pattern antiquote" pat_args

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

Looks like the problem's root is in qqDeclSpecE and qqDeclE function.

I'm trying to understand Type type:

data Type = Type DeclSpec Decl !SrcLoc
          | AntiType String !SrcLoc

What does DeclSpec field mean? And what Decl field mean?

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

Looks like DeclSpec is the base type (with qualifiers, without pointers), and Decl part is list(ish) of type modifiers (with their qualifiers).

from language-c-quote.

mainland avatar mainland commented on August 29, 2024

Here's what I would expect via substitution:

result = addConst intPtr
       = addConst [cty| int * |]
       = [cty| const int * |]

Why do you think the result should be int * const instead?

See also the $tyqual: antiquote.

DeclSpec and company will make more sense if you look at the C grammar.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

const int * and int const * mean mutable variable keeping address of immutable data.

int * const means immutable variable keeping address of mutable data.

Let's ask our friend GCC:

int       *       mutToMut      = NULL;
int const *       mutToConst    = NULL;
int       * const constToMut    = NULL;
int const * const constToConst  = NULL;

void takesMutToMut      (int        *       );
void takesMutToConst    (int const  *       );
void takesConstToMut    (int        * const );
void takesConstToConst  (int const  * const );

takesMutToMut(mutToMut);
// OK: no surprise

// takesMutToMut(mutToConst);
// error: passing argument 1 of ‘takesMutToMut’ discards
// ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
// Indeed, you can't mutate data pointed by pointer-to-const.

takesMutToMut(constToMut);
// OK: value is copied from immutable variable to mutable

// takesMutToMut(constToConst);
// error: passing argument 1 of ‘takesMutToMut’ discards
// ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
// Indeed, you can't mutate data pointed by pointer-to-const.

takesMutToConst(mutToMut);
// OK: ability to mutate pointed data is revoked

takesMutToConst(mutToConst);
// OK: no surprise

takesMutToConst(constToMut);
// OK: value is copied from immutable variable to mutable,
// and ability to mutate pointed data is revoked

takesMutToConst(constToConst);
// OK: value is copied from immutable variable to mutable

takesConstToMut(mutToMut);
// OK: argument is immutable inside the function

// takesConstToMut(mutToConst);
// error: passing argument 1 of ‘takesConstToMut’ discards
// ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
// Indeed, you can't mutate data pointed by pointer-to-const.

takesConstToMut(constToMut);
// OK: no surprise

// takesConstToMut(constToConst);
// error: passing argument 1 of ‘takesConstToMut’ discards
// ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
// Indeed, you can't mutate data pointed by pointer-to-const.

takesConstToConst(mutToMut);
// OK: argument is immutable inside the function,
// and ability to mutate pointed data is revoked

takesConstToConst(mutToConst);
// OK: argument is immutable inside the function

takesConstToConst(constToMut);
// OK: ability to mutate pointed data is revoked

takesConstToConst(constToConst);
// OK: no surprise

from language-c-quote.

mainland avatar mainland commented on August 29, 2024

I am aware of the difference between the two types. I also understand what you are trying to do.

What I am saying is that the current behavior is expected, and, although we don't agree on this, it is the more natural behavior, i.e., what a programmer should expected "by substitution" as I stated above.

I expect both the following to hold:

let ty = [ctype|int|] in [ctype|const $ty:ty|] is equivalent to [ctype|const int|]

let ty = [ctype|int *|] in [ctype|const $ty:ty|] is equivalent to [ctype|const int *|]

However, you want let ty = [ctype|int *|] in [ctype|const $ty:ty|] to be equivalent to [ctype|int * const|]. I see why you want that, but I do not agree that that is the "correct" behavior. Moreover, what if I really did want [ctype|const int *|]? How would I get it?

I would be more amenable if you wanted let ty = [ctype|int *|] in [ctype|$ty:ty const|] to be equivalent to [ctype|int * const|]. However, that currently doesn't work.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

what if I really did want [ctype|const int *|]? How would I get it?

[ctype|const int *|] from [ctype|const $ty:ty|]? Do you want to make mutable type from immutable? C doesn't allow it.

[ctype|const int *|] from [ctype|int *|]? Hm... It should be something explicit like makeTargetTypeConst.

I just want LCQ type expressions behave like C typedefs, for example

typedef int * MutToMut;
typedef MutToMut const ConstToMut;
static_assert(std::is_same<ConstToMut, int * const>::value, "ConstToMut is right");
static_assert(!std::is_same<ConstToMut, int const *>::value, "ConstToMut is not wrong");

Why do you think that [ctype|const $ty:ty|] should change not the type of ty, but the type inside ty?

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

AFAIK, from C's point of view, [ctype|$ty:ty const|] must be identical to [ctype|const $ty:ty|], mustn't?

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

const keyword before type name:

typedef int * MutToMut;
typedef const MutToMut ConstToMut;
static_assert(std::is_same<ConstToMut, int * const>::value, "ConstToMut is right");
static_assert(!std::is_same<ConstToMut, const int *>::value, "ConstToMut is not wrong");

The same.

from language-c-quote.

mainland avatar mainland commented on August 29, 2024

Why do you think that [ctype|const $ty:ty|] should change not the type of ty, but the type inside ty?

As I explained above, I am reasoning by substitution. If I have a quasiquote [ctype|const $ty:ty|], I expect it to be equivalent to the quasiquote I get by substituting the variable ty for its quasiquote. Reasoning by substitution, if ty is [ctype|int *|], I therefore expect [ctype|const $ty:ty|] to be equivalent to [ctype|const int *|].

AFAIK, from C's point of view, [ctype|$ty:ty const|] must be identical to [ctype|const $ty:ty|], mustn't?

C doesn't support quasiquotes, so we can't "ask C." Reasoning by substitution, the two would be different if ty were [ctype|int *|].

[ctype|const int *|] from [ctype|int *|]? Hm... It should be something explicit like makeTargetTypeConst.

Pardon? What is makeTargetTypeConst? Are you saying I shouldn't be able to use quasiquotation to get what I want?

Bottom line: functional programmers use equational reasoning to reason about functional programs. I would like to preserve that reasoning principle where possible. The current behavior aligns with this desire, and I am not willing to change it. I understand you want a way to add qualifiers to the pointer inside a type, but changing the current behavior is not the way to fix this problem.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

I am reasoning by substitution.

Text substitution? Without safety and semantics? Like substitution of x = 2 + 3 into 1 * x * 4 = 1 * 2 + 3 * 4?

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

C doesn't support quasiquotes, so we can't "ask C."

C does support type substitution — typedef.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

Are you saying I shouldn't be able to use quasiquotation to get what I want?

I'm saying textual substitution should be done with textual templaters, and AST builder should build AST, not vice versa.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

The current behavior aligns with this desire

Actually, not.

I understand you want a way to add qualifiers to the pointer inside a type

No, current behavior is to add qualifiers inside, but I want to add qualifiers on top of a type.

from language-c-quote.

mainland avatar mainland commented on August 29, 2024

No, current behavior is to add qualifiers inside, but I want to add qualifiers on top of a type.

Well, it depends what one means by "inside" :) The current behavior is to modify the qualifier list in the declaration specifiers part of the type (the DeclSpec in the AST). The suggested behavior is to modify the list of qualifiers attached to the Ptr inside the Decl—that's what I meant by "inside" the type.

C does support type substitution — typedef.

You're right—type substitution in the quasiquoter does not behave like typedef. Both semantics are reasonable. I expect the current behavior, and you expect an antiquoted type to act like a typedef—that's fair.

I have code that relies on the current behavior, and I don't know who else might rely on the current behavior. Because it would be a breaking change, I'm not willing to make it right now. If a number of users want the change, then I'd certainly reconsider.

A better name for this issue would be "Semantics of type antiquotation is different from semantics of typedef", and a reference to Section 6.7.6.1 of N1570 (the C11 draft standard) would be useful.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

Guys asked me to emphasize one more time that all I want is equational reasoning, for example (in pseudo-C):

x = int *
const $x == const (int *)

when current implementation gives:

const $x == (const int) *

I should have started from this.

from language-c-quote.

cblp avatar cblp commented on August 29, 2024

Okay, I'll try to document this (counter-intuitive, in my opinion) behaviour of const (and volatile, too) and write my own addConst function doing exactly what I need.

from language-c-quote.

Related Issues (20)

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.