Carp icon indicating copy to clipboard operation
Carp copied to clipboard

at least a bug but maybe a feature request. maybe related to pull/1332?

Open rgkirch opened this issue 4 years ago • 11 comments

#ifndef NO_H_
#define NO_H_

typedef int ELEMENT;

#define SODIUM 11;

#endif // NO_H_
(Project.config "echo-compiler-cmd" true)
(Project.config "echo-c" true)
(use IO)

(relative-include "no.h")

(register-type ELEMENT "ELEMENT" [])

(register SODIUM ELEMENT "SODIUM")

(defn my-fun [ELEMENT]
  (case ELEMENT
    SODIUM "aha"
    "aww"))

(defn main []
  (println* (my-fun SODIUM)))
$ carp no.carp -x

freezes and I have to kill it

(register-type ELEMENT "ELEMENT") ;; changed this line
$ carp no.carp -x
I can’t find any implementation for the interface `=` of type (Fn [ELEMENT, ELEMENT] Bool) at line 155, column 12 in 'C:/Users/richie/notMyCode/scolsen/Carp/core/ControlMacros.carp'.

None of the possibilities have the correct signature:
    Bool.= : (Fn [Bool, Bool] Bool)
    RefBool.= : (Fn [(Ref Bool a), (Ref Bool b)] Bool)
    Pointer.eq : (Fn [(Ptr p), (Ptr p)] Bool)
    Pointer.ref-eq : (Fn [(Ref (Ptr p) tyvar-from-info-0_7_28), (Ref (Ptr p) tyvar-from-info-0_7_42)] Bool)
    Maybe.= : (Fn [(Ref (Maybe a) b), (Ref (Maybe a) b)] Bool)
    Result.= : (Fn [(Ref (Result a b) c), (Ref (Result a b) c)] Bool)
    Byte.= : (Fn [Byte, Byte] Bool)
    ByteRef.= : (Fn [(Ref Byte a), (Ref Byte b)] Bool)
    Int.= : (Fn [Int, Int] Bool)
    IntRef.= : (Fn [(Ref Int a), (Ref Int b)] Bool)
    Long.= : (Fn [Long, Long] Bool)
    LongRef.= : (Fn [(Ref Long a), (Ref Long b)] Bool)
    Double.= : (Fn [Double, Double] Bool)
    DoubleRef.= : (Fn [(Ref Double a), (Ref Double b)] Bool)
    Float.= : (Fn [Float, Float] Bool)
    FloatRef.= : (Fn [(Ref Float a), (Ref Float b)] Bool)
    Pair.= : (Fn [(Ref (Pair a b) c), (Ref (Pair a b) c)] Bool)
    Triple.= : (Fn [(Ref (Triple a b c) d), (Ref (Triple a b c) d)] Bool)
    Quadruple.= : (Fn [(Ref (Quadruple a b c d) e), (Ref (Quadruple a b c d) e)] Bool)
    Array.= : (Fn [(Ref (Array a) b), (Ref (Array a) b)] Bool)
    StaticArray.= : (Fn [(Ref (StaticArray a) b), (Ref (StaticArray a) b)] Bool)
    Int8.= : (Fn [Int8, Int8] Bool)
    Int8Extra.= : (Fn [(Ref Int8 a), (Ref Int8 b)] Bool)
    Int16.= : (Fn [Int16, Int16] Bool)
    Int16Extra.= : (Fn [(Ref Int16 a), (Ref Int16 b)] Bool)
    Int32.= : (Fn [Int32, Int32] Bool)
    Int32Extra.= : (Fn [(Ref Int32 a), (Ref Int32 b)] Bool)
    Int64.= : (Fn [Int64, Int64] Bool)
    Int64Extra.= : (Fn [(Ref Int64 a), (Ref Int64 b)] Bool)
    Uint8.= : (Fn [Uint8, Uint8] Bool)
    Uint8Extra.= : (Fn [(Ref Uint8 a), (Ref Uint8 b)] Bool)
    Uint16.= : (Fn [Uint16, Uint16] Bool)
    Uint16Extra.= : (Fn [(Ref Uint16 a), (Ref Uint16 b)] Bool)
    Uint32.= : (Fn [Uint32, Uint32] Bool)
    Uint32Extra.= : (Fn [(Ref Uint32 a), (Ref Uint32 b)] Bool)
    Uint64.= : (Fn [Uint64, Uint64] Bool)
    Uint64Extra.= : (Fn [(Ref Uint64 a), (Ref Uint64 b)] Bool)
    Char.= : (Fn [Char, Char] Bool)
    CharRef.= : (Fn [(Ref Char a), (Ref Char b)] Bool)
    String.= : (Fn [(Ref String tyvar-from-info-0_14_30), (Ref String tyvar-from-info-0_14_38)] Bool)
    StringCopy.= : (Fn [String, String] Bool)
    Pattern.= : (Fn [(Ref Pattern tyvar-from-info-0_96_24), (Ref Pattern tyvar-from-info-0_96_33)] Bool)
    Map.= : (Fn [(Ref (Map a b) c), (Ref (Map a b) c)] Bool)
    Set.= : (Fn [(Ref (Set a) b), (Ref (Set a) b)] Bool)
    Unit.= : (Fn [(), ()] Bool)
    UnitRef.= : (Fn [(Ref () a), (Ref () b)] Bool) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:2.

Traceback:
  (defn my-fun [ELEMENT] (case ELEMENT SODIUM "aha" "aww")) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:1.

Ok, I guess. It doesn't know anything so it can't generate a check for equality...? I was hoping that the register-type E "E" [] form would help with that but it's stuck in a loop. It doesn't seem unreasonable to expect to be able to test equality even for opaque types when I'm only testing one ELEMENT against another ELEMENT. I think bit for bit equality would work. My use case: I expect windows to call my function with a MSG and I just need to know if it matches WM_SIZE or WM_CLOSE etc. They're acting like enumerations.

(Project.config "echo-compiler-cmd" true)
(Project.config "echo-c" true)
(use IO)

(relative-include "no.h")

(register-type ELEMENT "ELEMENT")

(register SODIUM Int "SODIUM") ;; changed ELEMENT to Int

(defn my-fun [ELEMENT]
  (case ELEMENT
    SODIUM "aha"
    "aww"))

(defn main []
  (println* (my-fun SODIUM)))

$ carp no.carp -x
The reference '(let [gensym-generated1037 ELEMENT] (if (Int.= gensym-generated1037 SODIUM) (do "aha") (do "aww")))' (depending on the variable '_19') isn't alive at line 0, column 0 in 'dummy-file'. at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:2.

Traceback:
  (defn my-fun [ELEMENT] (case ELEMENT SODIUM "aha" "aww")) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:1.

That's probably not what's supposed to happen.

I tried each example on master as the branch for https://github.com/carp-lang/Carp/pull/1332 and got the same results in each case.

rgkirch avatar Oct 13 '21 22:10 rgkirch

I tried again since #1340 got merged and I think it's a new error. I didn't feel like opening a new issue though since it's the same example code.

I'd expect ELEMENT to shadow but I guess I can't use the type as a variable.

carp no.carp -x
I canΓÇÖt match the types `ELEMENT` and `(Fn [] ELEMENT)`. within `(= gensym-gener ... DIUM)`

  SODIUM : ELEMENT
  At line 13, column 5 in 'C:/Users/richie/Documents/org/projects/handmade-carp/no.carp'

  Expected second argument to '=' : (Fn [] ELEMENT)
  At line 155, column 12 in 'C:/Users/richie/carp-v0.5.3-x86_64-windows/core/ControlMacros.carp' at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:2.

Traceback:
  (defn my-fun [ELEMENT] (case ELEMENT SODIUM "aha" "aww")) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:1.

This is with

(Project.config "echo-compiler-cmd" true)
(Project.config "echo-c" true)
(use IO)

(relative-include "no.h")

(register-type ELEMENT "ELEMENT" [])

(register SODIUM ELEMENT "SODIUM")

(defn my-fun [E]
  (case E
    SODIUM "aha"
    "aww"))

(defn main []
  (println* (my-fun SODIUM)))

rgkirch avatar Oct 22 '21 12:10 rgkirch

Edit no.h to #define SODIUM 11 as per https://github.com/carp-lang/Carp/issues/1348. The compile output is unchanged though so I'm not repasting it.

rgkirch avatar Dec 30 '21 15:12 rgkirch

I just pulled the latest code, stack build, stack install and I think it is the same output all around.

(register-type ELEMENT "ELEMENT")

$ carp no.carp -x
I can’t find any implementation for the interface `=` of type (Fn [ELEMENT, ELEMENT] Bool) at line 155, column 12 in 'C:/Users/richie/notMyCode/carp-lang/Carp/core/ControlMacros.carp'.

None of the possibilities have the correct signature:
    Bool.= : (Fn [Bool, Bool] Bool)
    RefBool.= : (Fn [(Ref Bool a), (Ref Bool b)] Bool)
    Box.= : (Fn [(Ref (Box a) b), (Ref (Box a) c)] Bool)
    Pointer.eq : (Fn [(Ptr p), (Ptr p)] Bool)
    Pointer.ref-eq : (Fn [(Ref (Ptr p) tyvar-from-info-0_7_28), (Ref (Ptr p) tyvar-from-info-0_7_42)] Bool)
    Maybe.= : (Fn [(Ref (Maybe a) b), (Ref (Maybe a) b)] Bool)
    Result.= : (Fn [(Ref (Result a b) c), (Ref (Result a b) c)] Bool)
    Byte.= : (Fn [Byte, Byte] Bool)
    ByteRef.= : (Fn [(Ref Byte a), (Ref Byte b)] Bool)
    Int.= : (Fn [Int, Int] Bool)
    IntRef.= : (Fn [(Ref Int a), (Ref Int b)] Bool)
    Long.= : (Fn [Long, Long] Bool)
    LongRef.= : (Fn [(Ref Long a), (Ref Long b)] Bool)
    Double.= : (Fn [Double, Double] Bool)
    DoubleRef.= : (Fn [(Ref Double a), (Ref Double b)] Bool)
    Float.= : (Fn [Float, Float] Bool)
    FloatRef.= : (Fn [(Ref Float a), (Ref Float b)] Bool)
    Pair.= : (Fn [(Ref (Pair a b) c), (Ref (Pair a b) c)] Bool)
    Triple.= : (Fn [(Ref (Triple a b c) d), (Ref (Triple a b c) d)] Bool)
    Quadruple.= : (Fn [(Ref (Quadruple a b c d) e), (Ref (Quadruple a b c d) e)] Bool)
    Array.= : (Fn [(Ref (Array a) b), (Ref (Array a) b)] Bool)
    StaticArray.= : (Fn [(Ref (StaticArray a) b), (Ref (StaticArray a) b)] Bool)
    Int8.= : (Fn [Int8, Int8] Bool)
    Int8Extra.= : (Fn [(Ref Int8 a), (Ref Int8 b)] Bool)
    Int16.= : (Fn [Int16, Int16] Bool)
    Int16Extra.= : (Fn [(Ref Int16 a), (Ref Int16 b)] Bool)
    Int32.= : (Fn [Int32, Int32] Bool)
    Int32Extra.= : (Fn [(Ref Int32 a), (Ref Int32 b)] Bool)
    Int64.= : (Fn [Int64, Int64] Bool)
    Int64Extra.= : (Fn [(Ref Int64 a), (Ref Int64 b)] Bool)
    Uint8.= : (Fn [Uint8, Uint8] Bool)
    Uint8Extra.= : (Fn [(Ref Uint8 a), (Ref Uint8 b)] Bool)
    Uint16.= : (Fn [Uint16, Uint16] Bool)
    Uint16Extra.= : (Fn [(Ref Uint16 a), (Ref Uint16 b)] Bool)
    Uint32.= : (Fn [Uint32, Uint32] Bool)
    Uint32Extra.= : (Fn [(Ref Uint32 a), (Ref Uint32 b)] Bool)
    Uint64.= : (Fn [Uint64, Uint64] Bool)
    Uint64Extra.= : (Fn [(Ref Uint64 a), (Ref Uint64 b)] Bool)
    Char.= : (Fn [Char, Char] Bool)
    CharRef.= : (Fn [(Ref Char a), (Ref Char b)] Bool)
    String.= : (Fn [(Ref String tyvar-from-info-0_14_30), (Ref String tyvar-from-info-0_14_38)] Bool)
    StringCopy.= : (Fn [String, String] Bool)
    Pattern.= : (Fn [(Ref Pattern tyvar-from-info-0_95_24), (Ref Pattern tyvar-from-info-0_95_33)] Bool)
    Map.= : (Fn [(Ref (Map a b) c), (Ref (Map a b) c)] Bool)
    Set.= : (Fn [(Ref (Set a) b), (Ref (Set a) b)] Bool)
    Unit.= : (Fn [(), ()] Bool)
    UnitRef.= : (Fn [(Ref () a), (Ref () b)] Bool) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:2.

Traceback:
  (defn my-fun [ELEMENT] (case ELEMENT SODIUM "aha" "aww")) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:1.

(register-type ELEMENT "ELEMENT" [])

$ carp no.carp -x
I can’t match the types `ELEMENT` and `(Fn [] ELEMENT)`. within `(= gensym-gener ... DIUM)`

  SODIUM : ELEMENT
  At line 13, column 5 in 'C:/Users/richie/Documents/org/projects/handmade-carp/no.carp'

  Expected second argument to '=' : (Fn [] ELEMENT)
  At line 155, column 12 in 'C:/Users/richie/notMyCode/carp-lang/Carp/core/ControlMacros.carp' at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:2.

Traceback:
  (defn my-fun [ELEMENT] (case ELEMENT SODIUM "aha" "aww")) at C:/Users/richie/Documents/org/projects/handmade-carp/no.carp:11:1.

no.h

#ifndef NO_H_
#define NO_H_

typedef int ELEMENT;

#define SODIUM 11

#endif // NO_H_

no.carp

(Project.config "echo-compiler-cmd" true)
(Project.config "echo-c" true)
(use IO)

(relative-include "no.h")

(register-type ELEMENT "ELEMENT" [])

(register SODIUM ELEMENT "SODIUM")

(defn my-fun [ELEMENT]
  (case ELEMENT
    SODIUM "aha"
    "aww"))

(defn main []
  (println* (my-fun SODIUM)))

rgkirch avatar Dec 30 '21 15:12 rgkirch

Welcome to Carp 0.5.4

rgkirch avatar Dec 30 '21 15:12 rgkirch

Should I not expect carp to generate equality for the type? I don't know that it's not just my misunderstanding.

rgkirch avatar Dec 30 '21 17:12 rgkirch

Right, it does not because there's no general way to define equality for a C type. It could be pointer comparison, structural equality or something else. So try implementing = for your type and the error should go away.

eriksvedang avatar Dec 30 '21 17:12 eriksvedang

We probably need to clarify that even more on this page https://github.com/carp-lang/Carp/blob/master/docs/CInterop.md#register-types

eriksvedang avatar Dec 30 '21 17:12 eriksvedang

Can I provide a c function to use for equality when I register the type? Can I register the type as an Int so that it's not opaque?

rgkirch avatar Dec 30 '21 18:12 rgkirch

Can I provide a c function to use for equality when I register the type?

You can't do it as part of the register-type call, but you can do this. Assuming you have:

bool eq_element(ELEMENT x, ELEMENT y) {
  return x = y;
}

You can register this comparison function in carp as follows:

(register eq-element (Fn [ELEMENT ELEMENT] Bool) "eq_element")
(implements = eq-element)

Note that the implements call is necessary to tell carp that eq-element implements the = interface. This means you can use = on element type values and Carp will correctly use eq-element; e.g. (= some-element some-other-element).

Can I register the type as an Int so that it's not opaque?

Sort of. You can register just a name for a type. You could use (register-type ELEMENT "int") -- this would have the effect of producing the typdef in your C header for you and you could get rid of the typedef you hardcoded. However, Carp will still treat ELEMENT as a separate type from Int--that's the whole point after all. If there's no need to maintain the distinction, just use Int directly. Unfortunately, Carp doesn't currently have type synonyms so there's no way to treat ELEMENT as the same as Int in Carp itself.

scolsen avatar Dec 30 '21 20:12 scolsen

Is the issue that register-type creates a new type when I actually want to use an existing type? Do I even need to register the type? I'm trying to emulate this code from Casey Muratori's Handmade Hero. I'm interfacing with the typedefs in windows.h. I just want to have windows hand me whatever UINT refers to (I know what it is if that helps) and then I'll compare it to other things defined in windows.h.

internal LRESULT CALLBACK
Win32MainWindowCallback(HWND Window,
                        UINT Message,
                        WPARAM WParam,
                        LPARAM LParam)
{       
    LRESULT Result = 0;

    switch(Message)
    {
        case WM_CLOSE:
        {
            // TODO(casey): Handle this with a message to the user?
            GlobalRunning = false;
        } break;

Maybe my simplified example is getting in the way of my understanding. Thanks for taking the time!

rgkirch avatar Dec 30 '21 22:12 rgkirch

I'm also trying to avoid writing c code or additional headers. Can I get by with just carp files or do I need to add a header? Sorry if I'm not coherent. I shelved carp after my initial effort so it's been a while. Looking at SDL.carp I think I would write code like:

(register-type ELEMENT)
(register SODIUM ELEMENT)

but that doesn't compile.

rgkirch avatar Dec 30 '21 23:12 rgkirch