tomhrr / dale

Lisp-flavoured C
BSD 3-Clause "New" or "Revised" License
1.03k stars 48 forks source link

Adding new concept macros to parametric types? #90

Closed porky11 closed 8 years ago

porky11 commented 8 years ago

I want to implement some simple vector-math (just adding arrays or vectors for now). So I would need to create concept-macros like +, which defines a function for the specified type. The type should have to implement some specific concept, like being able to create iterators. Also the elements of the Iterator type would have to implement the + function. Would I need to implement some parametric concept macro like (HasIterator Addable)? Is this even possible? Or how would this be done?

porky11 commented 8 years ago

I already made some simple working version (as long as I don't use it from other packages) without type-checking, https://github.com/porky11/planets/blob/working/src/sequence-math.dt#L22 (If you find something useful in my project, feel free, to add it to your repo)

tomhrr commented 8 years ago

On Sat, Sep 10, 2016 at 02:19:08PM -0700, Fabio Krapohl wrote:

I already made some simple working version (as long as I don't use it from other packages) without type-checking, https://github.com/porky11/planet0s/blob/working/src/sequence-math.dt#L22 (If you find something useful in my project, feel free, to add it to your repo)

An example of how to do this with a function expansion:

(import cstdio)
(import macros)
(import stdlib)
(import array)
(import concepts)
(import assert)
(import algorithms)

(using-namespace std.macros
(using-namespace std.concepts
  (def-concept Addable (refines Type) (T)
    (let ((success \ true))
      (concept-assert
        (exists-fn mc (qq (uq T) + (uq T) (uq T)))
        T "+ is not defined over this type")
      success))

  (def-concept-macro + extern ((T Container))
    (assert-concept (value-type (nullptr (uq T))) Addable)
    (using-namespace std.macros
    (qq do
      (import unistd)
      (def + (fn extern (retval (uq T)) ((a (uq T)) (b (uq T)))
        (let ((size \ (size a)))
          (and (!= (size a) (size b))
            (do (fprintf stderr "containers are not of equal size\n")
                (abort)))
          (let ((ab \ (begin a))
                (bb \ (begin b))
                (ob \ (begin (@ retval)))
                (ae \ (end a)))
            (for true (!= ab ae) (do (setv ab (successor ab))
                                     (setv bb (successor bb))
                                     (setv ob (successor ob)))
              (sink ob (+ (@ (source ab))
                          (@ (source bb)))))))
        (return))))))

  (implement Addable float)
  (instantiate Array float 2)
  (instantiate + (Array float 2))
))

(def main (fn extern-c int (void)
  (def x (var auto (Array float 2)))
  (setf ($ x 0) 0.1)
  (setf ($ x 1) 0.2)
  (def y (var auto (Array float 2)))
  (setf ($ y 0) 0.3)
  (setf ($ y 1) 0.4)
  (setv x (+ x y))
  (printf "%f %f\n" (@$ x 0) (@$ x 1))
  0))

This uses the 'concept-assert' macro from the 'concept-defs' module, as well as the 'assert-concept' macro from the 'algorithms' module (not great names). '+' should be checking that the iterator for 'T' implements 'OutputIterator', but cannot at the moment, because there is no 'iterator-type' macro for containers. This is because the expectation was that most concept macros and expansions would take iterator arguments instead. (It's not difficult to add these macros to the core libraries, and there's no problem with doing so, it's just that they don't currently exist.)