Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion cabal.project
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
packages:
packages/*/*.cabal
packages/diagnostician
packages/diagnostician-terminal
packages/diagnostician-html
packages/fnotation
packages/coln-compiler
if !os(wasi)
packages:
packages/coln-manual-dev
packages/coln-do
packages/coln-repl
packages/coln-ls
packages/coln-cli
else
packages:
packages/coln-wasm

jobs: $ncpus
semaphore: true
tests: True
Expand All @@ -9,3 +24,10 @@ constraints:
-- https://github.com/haskell/lsp/issues/641
lsp >= 2.8.0.0,
lsp-types >= 2.4,

if impl(ghc >= 9.14)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we're keeping GHC 9.12 for native builds, but using 9.14 for Wasm, since that's moving fast and improvements haven't been getting backported.

Fortunately, no code in Coln is broken by the update, and ecosystem support is mostly there now. Just the two packages needing bounds tweaked. One of them is mine and should now actually work, but I don't want to force everyone in to a cabal update.

allow-newer:
-- https://github.com/dmwit/ordered-containers/pull/36
ordered-containers:containers,
-- https://github.com/georgefst/prettyprinter-lucid/issues/7
prettyprinter-lucid:base,
77 changes: 74 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay.url = "github:oxalica/rust-overlay";
ghc-wasm-meta.url = "gitlab:haskell-wasm/ghc-wasm-meta?host=gitlab.haskell.org";
};
outputs =
inputs@{
Expand Down Expand Up @@ -156,6 +157,7 @@
};

inherit (packages) forester coln-manual-dev;
haskell-wasm = inputs.ghc-wasm-meta.packages.${system}.default;
in
{
inherit packages;
Expand All @@ -177,9 +179,11 @@
forester
fourmolu
esbuild
haskell-wasm
haskell.compiler.ghc912
haskell.packages.ghc912.haskell-language-server
haskellPackages.cabal-gild
jq
just
nodejs
pnpm
Expand All @@ -190,6 +194,7 @@
openssl
pkg-config
reuse
simple-http-server
tectonic
typescript
zlib
Expand Down
2 changes: 1 addition & 1 deletion packages/coln-cli/coln-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ executable coln
Coln.CLI.REPL

build-depends:
base ^>=4.21.0.0,
base ^>=4.21.0.0 || ^>=4.22,
coln-compiler,
coln-ls,
coln-repl,
Expand Down
2 changes: 1 addition & 1 deletion packages/coln-do/coln-do.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ executable coln-do
default-language: GHC2024
ghc-options: -Wall
build-depends:
base ^>=4.21.0.0,
base ^>=4.21.0.0 || ^>=4.22,
bytestring,
directory,
djot,
Expand Down
2 changes: 1 addition & 1 deletion packages/coln-manual-dev/coln-manual-dev.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ executable coln-manual-dev
main-is: Main.hs
build-depends:
async,
base ^>=4.21.0.0,
base ^>=4.21.0.0 || ^>=4.22,
bytestring,
directory,
extra,
Expand Down
71 changes: 71 additions & 0 deletions packages/coln-wasm/Lib.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
-- SPDX-FileCopyrightText: 2026 Coln contributors
--
-- SPDX-License-Identifier: Apache-2.0 OR MIT

module Lib () where

import Coln.Backend.IR qualified as I
import Coln.Backend.Lower
import Coln.Core.Globals
import Coln.Diagnostics
import Coln.Frontend.Driver
import Control.Monad
import Data.Aeson.Text qualified as Aeson
import Data.Foldable
import Data.IORef
import Data.Map.Ordered qualified as OMap
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Lazy qualified as TL
import Diagnostician
import Diagnostician.HTML (diagnosticToHtml)
import Foreign.StablePtr
import GHC.Wasm.Prim
import Lucid qualified
import Prettyprinter
import Prettyprinter.Render.Text qualified as Text

data CompileResult = CompileResult
{ ir :: [I.FlatRealm]
, diagnostics :: [Diagnostic ColnCode]
}
foreign export javascript "freeCompileResult" freeStablePtr :: StablePtr CompileResult -> IO ()

compile :: JSString -> IO (StablePtr CompileResult)
compile src = do
ref <- newIORef []
globals <- topFromText (pureReporter ref) (newFile "<wasm>" $ textFromJSString src)
let ir = map (uncurry lowerRealm) $ OMap.assocs globals.realms
diagnostics <- reverse <$> readIORef ref
newStablePtr CompileResult{ir, diagnostics}
foreign export javascript "compile" compile :: JSString -> IO (StablePtr CompileResult)

getDiagnostics :: Bool -> StablePtr CompileResult -> IO JSVal
getDiagnostics asHtml = jsStringArray . map (textToJSString . TL.toStrict . render) . (.diagnostics) <=< deRefStablePtr
where
render =
if asHtml
then Lucid.renderText . diagnosticToHtml
else Text.renderLazy . layoutPretty defaultLayoutOptions . dpretty
foreign export javascript "getDiagnostics" getDiagnostics :: Bool -> StablePtr CompileResult -> IO JSVal

prettyIr :: StablePtr CompileResult -> IO JSVal
prettyIr = jsStringArray . map (textToJSString . T.show) . (.ir) <=< deRefStablePtr
foreign export javascript "prettyIr" prettyIr :: StablePtr CompileResult -> IO JSVal

irToJson :: StablePtr CompileResult -> IO JSString
irToJson = fmap (textToJSString . TL.toStrict . Aeson.encodeToLazyText . (.ir)) . deRefStablePtr
foreign export javascript "irToJson" irToJson :: StablePtr CompileResult -> IO JSString

textToJSString :: Text -> JSString
textToJSString = toJSString . T.unpack
textFromJSString :: JSString -> Text
textFromJSString = T.pack . fromJSString

foreign import javascript unsafe "[]" js_new_array :: IO JSVal
foreign import javascript unsafe "$1.push($2)" js_push_string :: JSVal -> JSString -> IO ()
jsStringArray :: [JSString] -> IO JSVal
jsStringArray ss = do
arr <- js_new_array
for_ ss $ js_push_string arr
pure arr
31 changes: 31 additions & 0 deletions packages/coln-wasm/coln-wasm.cabal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe best to call this coln-compiler-wasm to make it clear that this is about exposing the compiler to wasm rather than the runtime.

@georgefst georgefst Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll save that until last in order to simplify the diffs.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
cabal-version: 3.4
name: coln-wasm
version: 0.1

executable coln-wasm
Comment thread
olynch marked this conversation as resolved.
main-is: Lib.hs
hs-source-dirs: .
default-language: GHC2024
default-extensions:
NoFieldSelectors
OverloadedRecordDot
OverloadedStrings

build-depends:
aeson,
base,
coln-compiler,
containers,
diagnostician,
diagnostician-html,
fnotation,
ghc-experimental,
lucid,
ordered-containers,
prettyprinter,
text,

ghc-options:
-Wall
-no-hs-main
-optl-mexec-model=reactor
Loading
Loading