Giter Club home page Giter Club logo

clojuredart's Introduction

What is ClojureDart?

ClojureDart is a recent Clojure dialect to make native mobile and desktop apps using Flutter and the Dart ecosystem.

It's production-ready: applications are being built with it.

Funding and Support

Clojuredart is developed by Baptiste Dupuch🐦 and Christophe Grand🐦 by taking time off of their consultancy -- it's grueling at times.

How can you help?

  • Sponsor us (individual sponsorship is nice but corporate sponshorship is great). You can sponsor any of us or both, it doesn't matter, we split (❀️ Baptiste ❀️ Christophe).
  • Contract us for assistance, training, consulting or dev (can be as mundane as requesting to port a clj/cljs lib to cljd)

Cheatsheet

We have a cheatsheet covering ClojureDart specifics on one side and Flutter programming on the other side.

Conj 2023 talk and demo

Want to see what's the workflow like? Our talk at Clojure/Conj 2023 is mostly a live-coding session, starting from scratch and assuming no prior knowledge of Dart or Flutter! Click here or on the image πŸ‘‡

Where to find help?

Stop by the Clojurians #ClojureDart channel or open an issue.

Completeness Status

The two missing big features are:

  • no REPL yet (WIP), but we have excellent hot-reload during UI work to get instant feedback
  • multi-method (WIP)

Links dump

Slack Youtube Twitter

Don't forget to subscribe to Curiosities -- our newsletter on ClojureDart and more!

Your first app!

Prerequisites: Clojure and Flutter installed and on your path.

Create a project directory with its deps.edn

mkdir hello
cd hello
cat << EOF > deps.edn
{:paths ["src"] ; where your cljd files are
 :deps {tensegritics/clojuredart
        {:git/url "https://github.com/tensegritics/ClojureDart.git"
         :sha "75665e2018b5c373b2e90d2299579fec7f94b3db"}}
 :aliases {:cljd {:main-opts ["-m" "cljd.build"]}}
 :cljd/opts {:kind :flutter
             :main acme.main}}
EOF

(To update an existing project to the latest ClojureDart, just do clj -M:cljd upgrade)

Initialize project:

clj -M:cljd init

Add some source code:

mkdir -p src/acme
cat << EOF > src/acme/main.cljd
(ns acme.main
  (:require ["package:flutter/material.dart" :as m]
            [cljd.flutter :as f]))

(defn main []
  (f/run
    (m/MaterialApp
      .title "Welcome to Flutter"
      .theme (m/ThemeData .primarySwatch m.Colors/pink))
    .home
    (m/Scaffold
      .appBar (m/AppBar
                .title (m/Text "Welcome to ClojureDart")))
    .body
    m/Center
    (m/Text "Let's get coding!"
       .style (m/TextStyle
                .color m.Colors/red
                .fontSize 32.0))))
EOF

Compile, watch and run:

clj -M:cljd flutter

In most environments this will spawn a desktop app.

More details there

Quick starts

Examples

In the samples directory directory, you'll find original sample code and ports of Flutter recipes.

How to run a sample project

Clone the ClojureDart repo.

git clone https://github.com/Tensegritics/ClojureDart.git

Go to the sample you want to try, let's say fab:

cd ClojureDart/samples/fab

Init the project:

clj -M:cljd init

Then launch the watcher:

clj -M:cljd flutter

You should get the sample running either in Chrome or as a desktop app.

To specify your exact target you must run flutter devices which outputs something like:

3 connected devices:
iPhone 6s (mobile) β€’ D6707352-78D2-46BB-AB95-87355283FC82 β€’ ios            β€’
com.apple.CoreSimulator.SimRuntime.iOS-15-5 (simulator)
macOS (desktop)    β€’ macos                                β€’ darwin-arm64   β€’
macOS 12.4 21F79 darwin-arm
Chrome (web)       β€’ chrome                               β€’ web-javascript β€’
Google Chrome 103.0.5060.114

The second column is the id of the target (here D6707352-78D2-46BB-AB95-87355283FC82, macos or chrome) that you pass to the watcher:

clj -M:cljd flutter -d D6707352-78D2-46BB-AB95-87355283FC82

Enjoy! πŸ§ƒ

cljd.flutter

cljd.flutter is an utility namespace to remove Flutter boilerplate and integrate more nicely with Clojure.

cljd.flutter.alpha

Deprecated, use cljd.flutter.

cljd.flutter.alpha2

Got out of alpha status and lives a happy life as cljd.flutter.

Thanks!

To all individuals who blindly believed in our endeavor and sponsored our work.

To NuBank who approached us very early for sponsorship.

To Roam Research who bet their mobile apps development (now in the App Store and Play Store) on ClojureDart and allowed us to make steady progress since Summer 2021.

If you want to sponsor our work, you can sponsor either of us, we'll balance sponsorship. If you are a company you can also contact us directly.

clojuredart's People

Contributors

bowbahdoe avatar brandonstubbs avatar cgrand avatar d00mch avatar djblue avatar dupuchba avatar frankitox avatar ianffcs avatar jolby avatar lambdina avatar panterarocks49 avatar paulhempel avatar pawelstroinski avatar perpen avatar pfeodrippe avatar prestancedesign avatar quantum-musician avatar rogererens avatar valerauko avatar wevre avatar zackteo avatar zhoumin79 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

clojuredart's Issues

How to pass dart method as a parameter?

I write wrappers over http.dart, and can't figure out how to pass http/<method-name> as an argument to the function.

For example, I have my post method as:

(defn post [url {:keys [headers on-success on-error body params]}]
  (. (http/post 
       (.parse Uri (if params (str url "?" (params->query-string params)) url)) 
       :body (some-> body stringify-keys convert.json/encode) 
       :headers (when headers ^#/(Map String String) headers)) 

     (then #(when-let [callback (if (= (.-statusCode %) 200) on-success on-error)]
              (callback (-> % .-body utils/keywordize-blunt))))

     (catchError #(when on-error (on-error %)))))

Having this, I want to avoid writing the same stuff for get, put, delete, and instead use one function and pass 'method' to it like:

;; as previous, but 'method' is used instead of 'http/post' 
(defn request [method url {:keys [headers on-success on-error body params]}]
  (. (method 
       ... 
       ) ...))

(defn post [url args]
  (request http/get url args))
logs ``` You rock! 🀘

Performing hot reload...

══║ EXCEPTION CAUGHT BY WIDGETS LIBRARY β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
The following NoSuchMethodError was thrown building Builder(dirty):
Closure call with mismatched arguments: function 'get'
Receiver: Closure: (Uri, {Map<String, String>? headers}) => Future from Function 'get':
static.
Tried calling: get(Instance of '_SimpleUri', Instance of 'Keyword', null)
Found: get(Uri, {Map<String, String>? headers}) => Future

The relevant error-causing widget was:
MaterialApp
MaterialApp:file:///Users/m1/IdeaProjects/clojure/lconvex/lib/cljd-out/lconvex/main.dart:30:37

When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
#1 _objectNoSuchMethod (dart:core-patch/object_patch.dart:85:9)
#2 request (package:lconvex/cljd-out/lconvex/sdk.dart:172:33)
#3 post (package:lconvex/cljd-out/lconvex/sdk.dart:131:22)
#4 init (package:lconvex/cljd-out/lconvex/sdk.dart:34:22)
#5 accounts_page (package:lconvex/cljd-out/lconvex/main.dart:12:15)
#6 MaterialPageRoute.buildContent (package:flutter/src/material/page.dart:53:55)
#7 MaterialRouteTransitionMixin.buildPage (package:flutter/src/material/page.dart:106:27)
#8 _ModalScopeState.build.. (package:flutter/src/widgets/routes.dart:872:55)
#9 Builder.build (package:flutter/src/widgets/basic.dart:7398:48)
#10 StatelessElement.build (package:flutter/src/widgets/framework.dart:4827:28)
#11 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4754:15)
#12 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#13 StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
#14 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
derObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#16 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#17 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#18 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#22 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#23 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#24 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#25 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
gets/framework.dart:6291:14)ectElement.update (package:flutter/src/wid
#27 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#28 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#29 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#30 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#31 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#32 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#33 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#34 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#35 StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
#36 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#37 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
utter/src/widgets/framework.dart:4928:11)ackage:fl
#39 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#40 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#41 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#42 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#43 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#44 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#45 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#46 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#47 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#48 ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
#49 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:111:11)
ateChild (package:flutter/src/widgets/framework.dart:3501:15)
#51 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#52 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#53 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#54 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#55 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#56 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#57 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#58 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#59 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#60 ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
#61 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
ntElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#63 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#64 ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
#65 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#66 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#67 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#68 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#69 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#70 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#71 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#72 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#73 StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
ateChild (package:flutter/src/widgets/framework.dart:3501:15)
#75 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#76 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#77 StatelessElement.update (package:flutter/src/widgets/framework.dart:4834:5)
#78 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#79 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6291:14)
#80 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#81 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#82 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#83 ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
#84 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#85 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
nt.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#87 ProxyElement.update (package:flutter/src/widgets/framework.dart:5108:5)
#88 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#89 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#90 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#91 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#92 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
#93 Element.updateChild (package:flutter/src/widgets/framework.dart:3501:15)
#94 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#95 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#96 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#97 StatefulElement.update (package:flutter/src/widgets/framework.dart:4960:5)
ateChild (package:flutter/src/widgets/framework.dart:3501:15)
#99 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4780:16)
#100 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4928:11)
#101 Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#102 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#103 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#104 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
#105 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#106 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1081:9)
#107 SchedulerBinding.scheduleWarmUpFrame. (package:flutter/src/scheduler/binding.dart:862:7)
(elided 4 frames from class _RawReceivePortImpl, class _Timer, and dart:async-patch)

�════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 4 of 940 libraries in 775ms.

</details>

Reader conditional selects :clj branch if it comes before :cljd

see https://clojurians.slack.com/archives/C03A6GE8D32/p1650332155679279

;; okay
(println #?(:cljd 1
            :clj (Integer/parseInt "2")
            :default nil))
;; KO
(println #?(:clj (Integer/parseInt "2")
            :cljd 1
            :default nil))
Something horrible happened! 😱
Error while compiling Integer/parseInt
Integer/parseInt
(Integer/parseInt "2")
(println (Integer/parseInt "2"))
(let* [] (println (Integer/parseInt "2")))
(do (println (Integer/parseInt "2")))
(fn* ([] (println (Integer/parseInt "2"))))
(defn main [] (println (Integer/parseInt "2")))
Unknown symbol: Integer/parseInt at line: 5, column: 20, file: quickstart/helloworld.cljc

Handle named parameters for emitting Function type

We don't handle named parameters when creating pure dart functions.
There might be some very rare cases where a named parameters must be emitted when magic-casting a function
e.g: String Function(int, {String id})

Document compiler internals and how to extend it

Congrats to the release guys! Is there any chance we can have a document on how the compiler is implemented (more technical details) and how to extend it? I think it can be also useful for someone who wants to try with a new backend

swap! subvec breaks vector structure

This sequence:

(let [q (atom [])
        qpush (fn [q val] (swap! q conj val))
        qpop (fn [q]
               (let [val (first @q)]
                 (swap! q #(doall (subvec % 1)))
                 val))]
    (qpush q 0)
    (qpush q 1)
    (let [p1 (qpop q)]
      (qpush q 2) ;; <- necessary ingredient
      (let [p2 (qpop q)]
        (prn :qpop2 p2)
        (prn :q @q))))

...fails like this during the second qpop:

[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: RangeError (index): Invalid value: Not in inclusive range 0..2: 3
#0      List.[] (dart:core-patch/array.dart:121:36)
#1      PVIterator.current (package:matrix/cljd-out/cljd/core.dart:12525:13)
#2      iterator_seq (package:matrix/cljd-out/cljd/core.dart:27415:66)
#3      IteratorSeq.$_rest$0 (package:matrix/cljd-out/cljd/core.dart:12172:51)
#4      IteratorSeq.$_next$0 (package:matrix/cljd-out/cljd/core.dart:12183:38)
#5      next (package:matrix/cljd-out/cljd/core.dart:29328:52)
#6      dorun$ifn.$_invoke$1 (package:matrix/cljd-out/cljd/core.dart:23451:24)
#7      doall$ifn.$_invoke$1 (package:matrix/cljd-out/cljd/core.dart:23406:23)
#8      main.qpop$1.<anonymous closure> (package:matrix/cljd-out/tiltontec/main.dart:44:31)
#9      Atom.$_swap$BANG_$1 (package:matrix/cljd-out/cljd/core.dart:3683:28)
#10     swap$BANG_$ifn.$_invoke$2 (package:matrix/cljd-out/cljd/core.dart:33376:17)
#11     main.qpop$1 (package:matrix/cljd-out/tiltontec/main.da<…>

Change the doall to do and it fails printing the vector after the second qpop:

[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: RangeError (index): Invalid value: Not in inclusive range 0..2: 3
#0      List.[] (dart:core-patch/array.dart:121:36)
#1      pv_reduce$ifn.$_invoke$5 (package:matrix/cljd-out/cljd/core.dart:30565:43)
#2      SubVec.$_reduce$2 (package:matrix/cljd-out/cljd/core.dart:16947:35)
#3      print_sequential (package:matrix/cljd-out/cljd/core.dart:30290:47)
#4      SubVec.$_print$1 (package:matrix/cljd-out/cljd/core.dart:16746:24)
#5      pr$ifn.$_invoke$vararg (package:matrix/cljd-out/cljd/core.dart:30069:43)
#6      IFnMixin_XZ.$_apply$1 (package:matrix/cljd-out/cljd/core.dart:6701:14)
#7      apply$ifn.$_invoke$2 (package:matrix/cljd-out/cljd/core.dart:18006:51)
#8      prn$ifn.$_invoke$vararg (package:matrix/cljd-out/cljd/core.dart:30355:23)
#9      IFnMixin_Z.$_invoke$2 (package:matrix/cljd-out/cljd/core.dart:6902:14)
#10     main (package:matrix/cljd-out/tiltontec/main.dart:54:29)
#11     _runMainZoned.<anonymous closure>.<anonymous closure> (dart:<…>

Error initializing project with clj version 1.10.3.822 on macOS

macOS 10.5.7
clj version 1.10.3.822

do init --dart xxx.main with error, but ok with clj version 1.11.1.1105. The document say I need clj at last 1.10.3.814 maybe a issue.

{:clojure.main/message
 "Syntax error (ClassNotFoundException) compiling at (clojure/tools/deps/alpha/util/s3_transporter.clj:1:1).\norg.eclipse.aether.RepositorySystemSession\n",
 :clojure.main/triage
 {:clojure.error/phase :compile-syntax-check,
  :clojure.error/line 1,
  :clojure.error/column 1,
  :clojure.error/source "s3_transporter.clj",
  :clojure.error/path
  "clojure/tools/deps/alpha/util/s3_transporter.clj",
  :clojure.error/class java.lang.ClassNotFoundException,
  :clojure.error/cause "org.eclipse.aether.RepositorySystemSession"},
 :clojure.main/trace
 {:via
  [{:type clojure.lang.Compiler$CompilerException,
    :message
    "Syntax error compiling at (clojure/tools/deps/alpha/util/s3_transporter.clj:1:1).",
    :data
    {:clojure.error/phase :compile-syntax-check,
     :clojure.error/line 1,
     :clojure.error/column 1,
     :clojure.error/source
     "clojure/tools/deps/alpha/util/s3_transporter.clj"},
    :at [clojure.lang.Compiler load "Compiler.java" 7648]}
   {:type java.lang.ClassNotFoundException,
    :message "org.eclipse.aether.RepositorySystemSession",
    :at
    [java.net.URLClassLoader findClass "URLClassLoader.java" 471]}],
  :trace
  [[java.net.URLClassLoader findClass "URLClassLoader.java" 471]
   [clojure.lang.DynamicClassLoader
    findClass
    "DynamicClassLoader.java"
    69]
   [java.lang.ClassLoader loadClass "ClassLoader.java" 589]
   [clojure.lang.DynamicClassLoader
    loadClass
    "DynamicClassLoader.java"
    77]
   [java.lang.ClassLoader loadClass "ClassLoader.java" 522]
   [java.lang.Class forName0 "Class.java" -2]
   [java.lang.Class forName "Class.java" 398]
   [clojure.lang.RT classForName "RT.java" 2211]
   [clojure.lang.RT classForNameNonLoading "RT.java" 2224]
   [clojure.tools.deps.alpha.util.s3_transporter$eval3905$loading__6721__auto____3906
    invoke
    "s3_transporter.clj"
    9]
   [clojure.tools.deps.alpha.util.s3_transporter$eval3905
    invokeStatic
    "s3_transporter.clj"
    9]
   [clojure.tools.deps.alpha.util.s3_transporter$eval3905
    invoke
    "s3_transporter.clj"
    9]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler eval "Compiler.java" 7166]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.core$require doInvoke "core.clj" 6007]
   [clojure.lang.RestFn invoke "RestFn.java" 457]
   [clojure.tools.deps.alpha.util.maven$eval3897$loading__6721__auto____3898
    invoke
    "maven.clj"
    9]
   [clojure.tools.deps.alpha.util.maven$eval3897
    invokeStatic
    "maven.clj"
    9]
   [clojure.tools.deps.alpha.util.maven$eval3897 invoke "maven.clj" 9]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler eval "Compiler.java" 7166]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.core$require doInvoke "core.clj" 6007]
   [clojure.lang.RestFn invoke "RestFn.java" 482]
   [clojure.tools.deps.alpha.extensions.maven$eval3889$loading__6721__auto____3890
    invoke
    "maven.clj"
    9]
   [clojure.tools.deps.alpha.extensions.maven$eval3889
    invokeStatic
    "maven.clj"
    9]
   [clojure.tools.deps.alpha.extensions.maven$eval3889
    invoke
    "maven.clj"
    9]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler eval "Compiler.java" 7166]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.tools.deps.alpha$eval3883 invokeStatic "alpha.clj" 820]
   [clojure.tools.deps.alpha$eval3883 invoke "alpha.clj" 820]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.core$require doInvoke "core.clj" 6007]
   [clojure.lang.RestFn invoke "RestFn.java" 1523]
   [clojure.tools.cli.api$eval3328$loading__6721__auto____3329
    invoke
    "api.clj"
    9]
   [clojure.tools.cli.api$eval3328 invokeStatic "api.clj" 9]
   [clojure.tools.cli.api$eval3328 invoke "api.clj" 9]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler eval "Compiler.java" 7166]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.core$require doInvoke "core.clj" 6007]
   [clojure.lang.RestFn invoke "RestFn.java" 551]
   [cljd.build$eval138$loading__6721__auto____139 invoke "build.clj" 9]
   [cljd.build$eval138 invokeStatic "build.clj" 9]
   [cljd.build$eval138 invoke "build.clj" 9]
   [clojure.lang.Compiler eval "Compiler.java" 7177]
   [clojure.lang.Compiler eval "Compiler.java" 7166]
   [clojure.lang.Compiler load "Compiler.java" 7636]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :cause "org.eclipse.aether.RepositorySystemSession",
  :phase :compile-syntax-check}}

automatic map spreading on interop calls with named parameters

When a method, function or constructor expects named parameters but that it receives an odd number of arguments (positional ones not counted) then the last argument is considered to evaluate to a map and is replaced by all missing parameters being passed valued looked up in the map.

It must be taken care of:

  • evaluating the map argument only once
  • re-emitting default values; problem is that some default values depend on private lib elements and so can't be injected in user-code, we should warn in such cases and treat them as required (unless nullable which is unlikely)
  • throwing an error at compile time if the call site is dynamic.

Clojure features parity

Umbrella issue.
Port missing libs (zip, xml?, cljd.dart.io etc.)
Add missing fns (at least clojure 1.11)

Mutation not happening for a deftype

I'm running the code below and I would expect {:v 40} as the output.

(ns quickstart.helloworld)

(defprotocol ITestProtocol
  (act [_ _]))

(deftype Test [^:mutable x-a]
  ITestProtocol
  (act [this o] (set! x-a o))

  Object
  (toString [this]
    (str x-a)))

(def t (Test. 10))
(act t 40)

(defn main []
  (print {:v t}))

But I'm having

{:v 10}

When I move (act t 40) to main, I have the following error

Unhandled exception:
Exception: No extension of protocol ITestProtocol found for type int.
#0      ITestProtocol$iprot.extensions (file:///Users/paulo.feodrippe/dev/dartapp/lib/cljd-out/quickstart/helloworld.dart:47:1)
#1      main (file:///Users/paulo.feodrippe/dev/dartapp/lib/cljd-out/quickstart/helloworld.dart:97:37)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#3      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

Plain Dart Quickstart compiles the wrong program when project root directory isn't exactly `helloworld`

Hello, thanks for your work with ClojureDart!

This is a follow-up from Clojurians Slack.

When following the instructions for the Plain Dart Quickstart, almost to the letter, I ended up with the wrong program being compiled. It prints Hello World!, and not the expected hello, world. The only part I didn't follow was that I did not name the project directory helloworld.

When I follow the instructions, including naming the project directory helloworld, it prints the expected message.

I published a repository containing both variants here: https://github.com/PEZ/clojuredart-quickstart-root-problem

I removed the .gitignore files, in case some otherwise ignored file contains some clue.

Watch process crashing on file change

I run the watch command from the tutorial:

clj -M -m cljd.build flutter

Platform: MacOS 11.6
Java: openjdk 17.0.1 2021-10-19 LTS
Clojure CLI version: 1.11.1.1107

Then after any changes to .cljd file I got the process crash:

{:clojure.main/message
 "Execution error (IOException) at java.lang.ProcessBuilder$NullOutputStream/write (ProcessBuilder.java:442).\nStream closed\n",
 :clojure.main/triage
 {:clojure.error/class java.io.IOException,
  :clojure.error/line 442,
  :clojure.error/cause "Stream closed",
  :clojure.error/symbol
  java.lang.ProcessBuilder$NullOutputStream/write,
  :clojure.error/source "ProcessBuilder.java",
  :clojure.error/phase :execution},
 :clojure.main/trace
 {:via
  [{:type java.io.IOException,
    :message "Stream closed",
    :at
    [java.lang.ProcessBuilder$NullOutputStream
     write
     "ProcessBuilder.java"
     442]}],
  :trace
  [[java.lang.ProcessBuilder$NullOutputStream
    write
    "ProcessBuilder.java"
    442]
   [java.io.OutputStream write "OutputStream.java" 157]
   [java.io.BufferedOutputStream
    flushBuffer
    "BufferedOutputStream.java"
    81]
   [java.io.BufferedOutputStream flush "BufferedOutputStream.java" 142]
   [sun.nio.cs.StreamEncoder implFlush "StreamEncoder.java" 318]
   [sun.nio.cs.StreamEncoder flush "StreamEncoder.java" 153]
   [java.io.OutputStreamWriter flush "OutputStreamWriter.java" 251]
   [cljd.build$compile_cli$compile_files__6707$fn__6708
    invoke
    "build.clj"
    218]
   [cljd.build$watch_dirs invokeStatic "build.clj" 56]
   [cljd.build$watch_dirs invoke "build.clj" 24]
   [cljd.build$compile_cli invokeStatic "build.clj" 236]
   [cljd.build$compile_cli doInvoke "build.clj" 175]
   [clojure.lang.RestFn invoke "RestFn.java" 457]
   [cljd.build$_main invokeStatic "build.clj" 373]
   [cljd.build$_main doInvoke "build.clj" 346]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.core$apply invokeStatic "core.clj" 665]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :cause "Stream closed"}}


Implement multimethods

@dupuchba has a first implementation of multimethods sans hierarchies but I'd like multimethods, protocols and IFn mixins to share the common extension mechanism.

Stabler names for anonymous classes

Anonymous classes have too random names and this hinders hot-reloading.

Proposal: create name from parent name (which we doesn't pass at the moment) + parent (extends) class + hash of mixins and ifaces + serial in case of conflict.

`emit-new` as a special case of `emit-dot`

In the wake of #52 and of the failed attempt at #53 (currently quick fixed), I came to the conclusion that emit-new as a special case of emit-dot. However my first attempt at merging them failed. I stumbled on several edge cases that we rely on -- leftovers from more lenient times.

I stumbled on issue with some types being emitted as (dart/type type-map) instead of just type-map, or even sometimes ^{:dart/type type-map} sym. It's a first incoherence.

I stumbled on errors with protocols being almost types but having dash in them (and yes (My-Record.) works in Clojure. So fixing constructor lookup for records is required.

Issues with members being missing during host-eval (especially on IProtocol).

A nice ball of hair to entangle.

`defmacro` compile time STDOUT generates Dart code

This one was a little hard to understand what was going on.

If I print something (e.g. with println) inside a defmacro (and the macro compilation is for a deftype (but it may occur for other cases)), the STDOUT goes to the generated code.

(ns example)

(defmacro instance?
  []
  (println '(1 + 4)))

(deftype SciVar []
  Object
  (toString [_]
    (not (instance?))))

throws

βœ— dart run

Building package executable...
Failed to build dartapp:dartapp:
lib/cljd-out/quickstart/helloworld.dart:16:1: Error: Expected an identifier, but got '('.
Try inserting an identifier before '('.
(1 + 4)
^

The generated code is something like

... imports ...

// BEGIN SciVar
class SciVar extends dc.Object {

const SciVar():super();
(1 + 4)     // <-- _O_ !!!!!!!!!!!!!!!!!!!!!

dc.String toString(){
return true;
}
}

// END SciVar

// BEGIN instance?
dc.dynamic instance$QMARK_(dc.dynamic $AMPERSAND_form$1, dc.dynamic $AMPERSAND_env$1, ){
final dc.List<dc.dynamic> fl$1=(dc.List<dc.dynamic>.filled(3, 1, ));
fl$1[1]=(Upfddlcoc_core.symbol.$_invoke$2(null, "+", ));
fl$1[2]=4;
final Upfddlcoc_core.PersistentList $1=Upfddlcoc_core.$_list_lit(fl$1, );
return (Upfddlcoc_core.println.$_invoke$1($1, ));
}

// END instance?

const for named constructor

Description

Allow adding ^:const for named constructor call/factory

Problem

--dart-define variables that could be get from (String/fromEnvirontment "KEY") returns empty string instead of original content because of flutter this issue flutter/flutter#55870. Allowing const when declaring will solve this.

I tried

(def ^:const key (String/fromEnvirontment "KEY"))

but the compiler seems to ignore the const meta

Slack - https://clojurians.slack.com/archives/C03A6GE8D32/p1651606676187039

Reify all literal types

All classes appearing as literals should be reified so has to allow for a true instance? function and multimethods hierarchies (#3).

Methods exposed by a reify type should allow to test if an instance is of this type and if a type is a subtype of another.

Subtyping matrix can be determined statically and only needs to cover types appearing as literals.

Unknown symbol when using `dart:mirrors`

Hi, I'm having errors when trying to use dart:mirrors.

(ns quickstart.helloworld
  (:require
   ["dart:mirrors" :as m]))

(defn main []
  (println (m/reflect Exception)))

throws (at build)

Oh noes! 😡
Error while compiling m/reflect
m/reflect
(m/reflect Exception)
(println (m/reflect Exception))
(let* [] (println (m/reflect Exception)))
(do (println (m/reflect Exception)))
(fn* ([] (println (m/reflect Exception))))
(defn main [] (println (m/reflect Exception)))
Unknown symbol: m/reflect at line: 12, column: 12, file: quickstart/helloworld.cljd

If I do

(ns quickstart.helloworld
  (:require
   ["dart:mirrors" :as m]))

(defn main []
  (println Exception))

, it generates the following dart code

import "dart:core" as dc;
import "helloworld.dart" as Upfddlcoq_helloworld;
import "../cljd/core.dart" as Upfddlcoc_core;
import "dart:mirrors" as d_mirrors;

// BEGIN main
dc.dynamic main(){
return (Upfddlcoc_core.println.$_invoke$1(dc.Exception, ));
}

// END main

If I manually add d_mirrors.reflect to the generated dart code

import "dart:core" as dc;
import "helloworld.dart" as Upfddlcoq_helloworld;
import "../cljd/core.dart" as Upfddlcoc_core;
import "dart:mirrors" as d_mirrors;

// BEGIN main
dc.dynamic main(){
  return (Upfddlcoc_core.println.$_invoke$1(d_mirrors.reflect(dc.Exception), )); // << CHANGED HERE
}

// END main

It works

➜  dartapp git:(test) βœ— dart run

Building package executable...
Built dartapp:dartapp.
InstanceMirror on Exception

Shouldn't m/reflect map to d_mirrors.reflect?

Publish cljd.flutter.labs

We wrote a small library helping us to handle state with Flutter.
It's not "perfect" yet but I am pretty sure it could help others.

TODOs:

  • extract functions from our privates projects
  • write documentation
  • Handle external API HTTP request

Record constructors

Constructors have 3 extra fields (meta, hash, ext-map), we should either make them optionals or use named constructors to provide simpler constructors

Transfer type inference of the expression to the var

Brain dump on this behavior:

  • Core issue (def x (constructor....)) x is dynamic
    • or more generally the inference of the expression doesn't transfer to the var
    • thus the user has to type hint the var itsef
  • Why is it like that?
    • Because so does Clojure
    • Because if you redef and that the inferred type change you have to recompile every code referring this var (and this may cascade) thus promising nothing is easier.
  • Right now we transitively recompile all dependants so we could transfer the inferred type without adding complexity. It will impact REPL design though, maybe stick to a broadly sweeping dependants recompilation for REPL too.
  • Conceptually the inferred type may be too precise when you think of types as contracts.

Fix await emit/write

Current for functions we infer async when await is present, we must do the same for methods

Can't init on Windows (probably because of "Path" env var naming)

I'm trying ClojureDart on windows, and it fails to do clj -M -m cljd.build init --dart cljdapp.calculator with NPE:

Execution error (NullPointerException) at cljd.build/exec (build.clj:129).
Cannot invoke "Object.getClass()" because "target" is null

Maybe path is nil on Windows because "path" variable is named "Path" and not "PATH"?

PS C:\Users\Vlaaad\Projects\cljd-test> clj                                                      
Clojure 1.10.3
user=> (-> (ProcessBuilder. []) .environment (get "PATH"))     
nil
user=> (-> (ProcessBuilder. []) .environment (get "Path")) 
"C:\\Progr..."

`const` by default

When we can infer an expression is const, we should tag it as such -- unless ^:no-const.

Case statement fails when used with a variable

Case statement fails when used with a variable with the following error:

Execution error (AssertionError) at cljd.compiler/emit-case* (compiler.cljc:1600).
Assert failed: (and (symbol? expr) (env expr))

ClojureDart version: 1e38014

Examples:

;; OK
(case :ios
  :ios "iOS"
  :android "Android"
  "not implemented")   => "iOS"

(defn case-test
  [os]
    (case os
      :ios "iOS"
      :android "Android"
      "not implemented"))

(case-test :ios)  => "iOS"

;; ERROR
(def os :ios)

(case os
  :ios "iOS"
  :android "Android"
  "not implemented")   => Execution error...

(let [the-os :ios]
    (case the-os
      :ios "iOS"
      :android "Android"
      "not implemented"))    => Execution error...

Currently working around this by using condp.

`?` is ignored for symbols that don't exist

(ns quickstart.helloworld)

(defn main []
  (println (boolean? true) "\n" (boolean? false) "\n" (boolean? 10)))

outputs

βœ— dart run

Building package executable...
Built dartapp:dartapp.
true
 false
 true

It seems boolean? is being parsed as boolean by the compiler (maybe because ? is special in Dart AND there is no boolean? in cljd.core?).

Reader conditional `:cljd` not working for `defmacro`

I'm calling (->Node 10 20) and I'm having an error when using the reader conditional :cljd to define the ->Node macro.

Oh noes! 😡
Error while compiling (->Node 10 20)

See definitions below

;; It works.
(defmacro ->Node
  [body stack])

;; It does not work (the error appears only when calling `->Node`).
#?(:cljd (defmacro ->Node
           [body stack]))

;; It works.
#?(:clj (defmacro ->Node
          [body stack]))

Errors when creating some types withouth dot

Can't crate custom objects (from detype).
Can't crate m/Duration object.
Can't set values without dash.

(ns acme.main
  (:require
   ["package:flutter/material.dart" :as m]))

(deftype Cat [name])

(defn ^m/Widget accounts-page [_]
  (m/Scaffold
    :backgroundColor m.Colors/green
    :body (m/Center
            :child (m/Text (str "Name: " (Cat. "jee")
                                (m/Duration.)
                                #_(Cat "bob")          ;; uncomment to reproduce first bug
                                #_(m/Duration))))))    ;; uncomment to reproduce second bug

(let [^#/(m/ValueNotifier bool) close-hint (m/ValueNotifier false)]
  (set! (.-value close-hint) false)
  #_(set! (.value close-hint) false)) ;; uncomment to reproduce third bug

(defn main []
  (m/runApp
    (m/MaterialApp
      :title "Welcome to Flutter"
      :theme (m/ThemeData :primarySwatch m.Colors/pink)
      :initialRoute "/" 
      :routes {"/" accounts-page})))

Namespace alias "str" clashes with function "str"

This .cljd:

(ns tiltontec.model.base
  (:require
    [clojure.string :as str]))

(defn dummy [& bits]
  (str/join "," bits))

...fails to compile:

Compiling to Dart... @06:34
  tiltontec.model.base
What doesn’t kill you, makes you stronger. πŸ€”
Error while compiling (str/join "," bits)
(str/join "," bits)
(clojure.core/let [] (str/join "," bits))
(clojure.core/let [] (clojure.core/let [] (str/join "," bits)))
(let* [] (clojure.core/let [] (clojure.core/let [] (str/join "," bits))))
(do (clojure.core/let [] (clojure.core/let [] (str/join "," bits))))
(reify :var-name dummy :name-hint nil cljd.core/IFnMixin_Z cljd.core/Fn cljd.core/IFn ($_invoke$vararg [this15542 bits] (clojure.core/let [] (str/join "," bits))))
(fn* ([& bits] (str/join "," bits)))
(defn dummy [& bits] (str/join "," bits))
No matching clause: str

Guessing the alias "str" gets confused with the cljd str. Changing the alias to sth like "cljdstr" is a workaround.

Application launch for 'com.example.hello' did not return a valid pid nor a launch error.

I get the following error when trying to run the "hello" Flutter app:

[18:53:10 hello]$ open -a Simulator
[18:53:16 hello]$ clj -M -m cljd.build flutter
Warming up `.clojuredart/libs-info.edn` (helps us emit better code)

Compiling cljd.core to Dart
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Compiling to Dart... @18:53
  acme.main
  I like when a plan comes together! πŸ‘¨β€πŸ¦³

Lauching flutter run
Launching lib/main.dart on iPhone 13 mini in debug mode...
Running Xcode build...
Xcode build done.                                            5.3s
Exception: Unable to launch com.example.hello on 8A799269-CB24-4E68-9644-D7CD91CFEAF1:
ProcessException: Process exited abnormally:
com.example.hello: 0

An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=3):
Application launch for 'com.example.hello' did not return a valid pid nor a launch error.
No such process
  Command: /usr/bin/arch -arm64e xcrun simctl launch 8A799269-CB24-4E68-9644-D7CD91CFEAF1 com.example.hello --enable-dart-profiling --enable-checked-mode --verify-entry-points
  --observatory-port=0
Error launching application on iPhone 13 mini.

Exception in thread "Thread-10" java.io.IOException: Stream closed
	at java.base/java.lang.ProcessBuilder$NullOutputStream.write(ProcessBuilder.java:445)
	at java.base/java.io.OutputStream.write(OutputStream.java:162)
	at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
	at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
	at java.base/sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:320)
	at java.base/sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:160)
	at java.base/java.io.OutputStreamWriter.flush(OutputStreamWriter.java:248)
	at cljd.build$compile_cli$fn__6683.invoke(build.clj:225)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:833)

This is on a 16" 2021 MacBook Pro running macOS Monterrey Version 12.3.1 (21E258) and Xcode Version 13.3.1 (13E500a)

Make calling a constructor without `new` nor ending `.` canon

In Dart, new has been deprecated and their notion of constructor is wide as they have:

  • default constructor
  • named constructors (to palliate the lack of overloads)
  • const (interning) constructors
  • factory constructors -- which are not even constructors any more IMO

So it's unclear when in ClojureDart . or new should be required and it adds little value (except potentially making some cljc works).

Thus I propose making officially new and ending . optional.

It's happens to already work but these codepaths should be checked to really work (especially w/ regards to type inference).

Problem with methods named arguments

The problem

Trying to rewrite code
router.define("/", handler: rootHandler);
with
(.define router "/" :handler root-handler)

Having the result:

lib/cljd-out/minataurus/main.dart:19:37: Error: Too many positional arguments: 1 allowed,
but 2 found.
Try removing the extra positional arguments.
return (UmIcmlcom_main.router.define(const UmIcmlcoc_core.Keyword(null, "handler",
297822107, ), UmIcmlcom_main.root_handler, ));

File with code.
Library: fluro: ^2.0.3

Reproduce steps

Pushed my current project with the issue.

git clone https://github.com/Liverm0r/minataurus.git
cd minataurus
clj -M -m cljd.build flutter

Tried

rm -rf clojuredart and restart the clj flutter.

Failed calling extension of Object

I tried to implement hive_flutter inside my project and it needs to be initialized using Hive.initFlutter() which initFlutter() is an extension inside the package.

But instead of calling the Hive.initFlutter() directly, it seems that generated dart always casting it back to dynamic so calling extension will fail

core from my project

(defn main ^:async []
  (let [local hive/Hive]
    (.initFlutter local)))

and generated dart file be

dc.dynamic main(){
final h_hive.HiveInterface local$1=h_hive_flutter.Hive;
(local$1 as dc.dynamic).initFlutter(); // fails here because of casting
}

the extension from package

part of hive_flutter;

/// Flutter extensions for Hive.
extension HiveX on HiveInterface {
  /// Initializes Hive with the path from [getApplicationDocumentsDirectory].
  ///
  /// You can provide a [subDir] where the boxes should be stored.
  Future<void> initFlutter([String? subDir]) async {
    WidgetsFlutterBinding.ensureInitialized();
    if (kIsWeb) return;

    var appDir = await getApplicationDocumentsDirectory();
    init(path_helper.join(appDir.path, subDir));
  }
}

CLI error

Restarted application in 871ms.
Error: NoSuchMethodError: 'initFlutter'
Dynamic call of null.
Receiver: Instance of 'HiveImpl'
Arguments: []
    at Object.throw_ [as throw] (http://localhost:61884/dart_sdk.js:5063:11)
    at Object.defaultNoSuchMethod (http://localhost:61884/dart_sdk.js:5497:15)
    at hive_impl.HiveImpl.new.noSuchMethod (http://localhost:61884/dart_sdk.js:6588:19)
    at Object.noSuchMethod (http://localhost:61884/dart_sdk.js:5494:30)
    at callNSM (http://localhost:61884/dart_sdk.js:5233:19)
    at Object._checkAndCall (http://localhost:61884/dart_sdk.js:5235:27)
    at Object.callMethod (http://localhost:61884/dart_sdk.js:5313:17)
    at Object.dsend (http://localhost:61884/dart_sdk.js:5316:17)
    at main$ (http://localhost:61884/packages/bgbtapp/cljd-out/bgbt/main.dart.lib.js:87:10)
    at main (http://localhost:61884/web_entrypoint.dart.lib.js:36:29)
    at main.next (<anonymous>)
    at http://localhost:61884/dart_sdk.js:40192:33
    at _RootZone.runUnary (http://localhost:61884/dart_sdk.js:40062:59)
    at _FutureListener.thenAwait.handleValue (http://localhost:61884/dart_sdk.js:34983:29)
    at handleValueCallback (http://localhost:61884/dart_sdk.js:35551:49)
    at Function._propagateToListeners (http://localhost:61884/dart_sdk.js:35589:17)
    at _Future.new.[_completeWithValue] (http://localhost:61884/dart_sdk.js:35437:23)
    at http://localhost:61884/dart_sdk.js:34617:46
    at _RootZone.runUnary (http://localhost:61884/dart_sdk.js:40062:59)
    at _FutureListener.then.handleValue (http://localhost:61884/dart_sdk.js:34983:29)
    at handleValueCallback (http://localhost:61884/dart_sdk.js:35551:49)
    at Function._propagateToListeners (http://localhost:61884/dart_sdk.js:35589:17)
    at _Future.new.[_completeWithValue] (http://localhost:61884/dart_sdk.js:35437:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:61884/dart_sdk.js:35458:35)
    at Object._microtaskLoop (http://localhost:61884/dart_sdk.js:40330:13)
dk.js:40336:13)crotaskLoop (http://localhost:61884/dart_s
    at http://localhost:61884/dart_sdk.js:35811:9
No extension of protocol IWithMeta found for type HiveImpl.

I tried removing manually as dc.dynamic in generated file and works well. Is there any way to force type to be not casted to dynamic?

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.