Skip to content
Merged
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
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ jobs:
run: if [ -f scripts/test ]; then nix develop -c bash ./scripts/test; fi

- name: Luacheck
run: nix develop -c luacheck --quiet --std lua51 --no-unused-args src/
run: nix develop -c luacheck --quiet --std lua51 --no-unused-args --max-line-length 130 src/

- name: Format check
run: nix fmt && git diff --exit-code
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/.*
!/.gitignore
!/.github/
!/.tidyrc.json
!/.lua-format
/output/
10 changes: 10 additions & 0 deletions .lua-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# LuaFormatter config for the hand-written FFI under src/.
# 2-space indent. Keep simple functions on one line; column_limit sits a few
# columns under luacheck's 130 limit because lua-format under-counts the leading
# indent and trailing comma, so this keeps every emitted line within 130.
indent_width: 2
use_tab: false
column_limit: 126
continuation_indent_width: 2
keep_simple_function_one_line: true
keep_simple_control_block_one_line: true
10 changes: 10 additions & 0 deletions .tidyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"importSort": "source",
"importWrap": "source",
"indent": 2,
"operatorsFile": null,
"ribbon": 1,
"typeArrowPlacement": "first",
"unicode": "source",
"width": 80
}
16 changes: 13 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ A PureScript→Lua FFI fork in the [`purescript-lua`](https://github.com/purescr

## Commands

All commands run inside the nix dev shell:

- Build: `nix develop -c ./scripts/build`
- Test (only if the fork has `scripts/test`): `nix develop -c bash ./scripts/test`
- Lint: `nix develop -c luacheck --quiet --std lua51 --no-unused-args src/`
- Lint: `nix develop -c luacheck --quiet --std lua51 --no-unused-args --max-line-length 130 src/`
- Format: `nix fmt` (check: `nix fmt && git diff --exit-code`)

## Formatting

`nix fmt` runs treefmt (`treefmt.nix`): nixfmt for Nix, `dhall format`, purs-tidy
for `*.purs` (config in `.tidyrc.json`), and LuaFormatter for the `*.lua` FFI
(config in `.lua-format`). LuaFormatter is used over StyLua because it keeps the
parentheses pslua's foreign-file parser requires. The Lua line budget is 130
columns, matching the `luacheck --max-line-length` above. The check is
content-based (`nix fmt && git diff --exit-code`) rather than `treefmt --ci`,
since the in-place formatters bump mtime even when content is unchanged, which
trips treefmt's `--fail-on-change`. CI and the pre-commit hook use it.

## Lua 5.1 target

Expand Down
23 changes: 22 additions & 1 deletion flake.lock

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

43 changes: 39 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,33 @@
inputs.nixpkgs.follows = "nixpkgs";
};
pslua.url = "github:purescript-lua/purescript-lua";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = { self, nixpkgs, flake-utils, purescript-overlay, pslua }:
flake-utils.lib.eachDefaultSystem (system:
outputs =
{
self,
nixpkgs,
flake-utils,
purescript-overlay,
pslua,
treefmt-nix,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ purescript-overlay.overlays.default ];
};
in {
treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
in
{
formatter = treefmtEval.config.build.wrapper;
checks.formatting = treefmtEval.config.build.check self;
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
dhall
Expand All @@ -31,8 +48,26 @@
spago-bin.spago-0_21_0
treefmt
];
# Install a content-based pre-commit hook. It compares the working
# tree diff before and after `nix fmt`, so it only objects to changes
# the formatter itself introduces (not the developer's existing
# unstaged work) and is not fooled by formatters that only bump mtime.
# Rewritten each shell entry to stay in sync with this flake.
shellHook = ''
hook=.git/hooks/pre-commit
if [ -d .git ]; then
printf '%s\n' \
'#!/usr/bin/env bash' \
'before=$(git diff)' \
'nix fmt >/dev/null 2>&1 || exit 0' \
Comment thread
Unisay marked this conversation as resolved.
'[ "$before" = "$(git diff)" ] || { echo "nix fmt changed files; re-stage them, then commit." >&2; exit 1; }' \
> "$hook"
chmod +x "$hook"
fi
'';
};
});
}
);

# --- Flake Local Nix Configuration ----------------------------
nixConfig = {
Expand Down
2 changes: 1 addition & 1 deletion spago.dhall
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ name = "purescript-lua-prelude"
, dependencies = [ ] : List Text
, dependencies = [] : List Text
, packages = ./packages.dhall
, sources = [ "src/**/*.purs" ]
}
24 changes: 21 additions & 3 deletions src/Control/Apply.purs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,33 @@ lift2 f a b = f <$> a <*> b

-- | Lift a function of three arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
lift3 :: forall a b c d f. Apply f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
lift3
:: forall a b c d f. Apply f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
lift3 f a b c = f <$> a <*> b <*> c

-- | Lift a function of four arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
lift4 :: forall a b c d e f. Apply f => (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
lift4
:: forall a b c d e f
. Apply f
=> (a -> b -> c -> d -> e)
-> f a
-> f b
-> f c
-> f d
-> f e
lift4 f a b c d = f <$> a <*> b <*> c <*> d

-- | Lift a function of five arguments to a function which accepts and returns
-- | values wrapped with the type constructor `f`.
lift5 :: forall a b c d e f g. Apply f => (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g
lift5
:: forall a b c d e f g
. Apply f
=> (a -> b -> c -> d -> e -> g)
-> f a
-> f b
-> f c
-> f d
-> f e
-> f g
lift5 f a b c d e = f <$> a <*> b <*> c <*> d <*> e
3 changes: 2 additions & 1 deletion src/Control/Bind.purs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ composeKleisli f g a = f a >>= g
infixr 1 composeKleisli as >=>

-- | Backwards Kleisli composition.
composeKleisliFlipped :: forall a b c m. Bind m => (b -> m c) -> (a -> m b) -> a -> m c
composeKleisliFlipped
:: forall a b c m. Bind m => (b -> m c) -> (a -> m b) -> a -> m c
composeKleisliFlipped f g a = f =<< g a

infixr 1 composeKleisliFlipped as <=<
Expand Down
15 changes: 12 additions & 3 deletions src/Data/BooleanAlgebra.purs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@ class HeytingAlgebra a <= BooleanAlgebra a
instance booleanAlgebraBoolean :: BooleanAlgebra Boolean
instance booleanAlgebraUnit :: BooleanAlgebra Unit
instance booleanAlgebraFn :: BooleanAlgebra b => BooleanAlgebra (a -> b)
instance booleanAlgebraRecord :: (RL.RowToList row list, BooleanAlgebraRecord list row row) => BooleanAlgebra (Record row)
instance booleanAlgebraRecord ::
( RL.RowToList row list
, BooleanAlgebraRecord list row row
) =>
BooleanAlgebra (Record row)

instance booleanAlgebraProxy :: BooleanAlgebra (Proxy a)

-- | A class for records where all fields have `BooleanAlgebra` instances, used
-- | to implement the `BooleanAlgebra` instance for records.
class BooleanAlgebraRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint
class HeytingAlgebraRecord rowlist row subrow <= BooleanAlgebraRecord rowlist row subrow | rowlist -> subrow
class BooleanAlgebraRecord
:: RL.RowList Type -> Row Type -> Row Type -> Constraint
class
HeytingAlgebraRecord rowlist row subrow <=
BooleanAlgebraRecord rowlist row subrow
| rowlist -> subrow

instance booleanAlgebraRecordNil :: BooleanAlgebraRecord RL.Nil row ()

Expand Down
5 changes: 4 additions & 1 deletion src/Data/Bounded.purs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ instance boundedProxy :: Bounded (Proxy a) where
top = Proxy

class BoundedRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint
class OrdRecord rowlist row <= BoundedRecord rowlist row subrow | rowlist -> subrow where
class
OrdRecord rowlist row <=
BoundedRecord rowlist row subrow
| rowlist -> subrow where
topRecord :: Proxy rowlist -> Proxy row -> Record subrow
bottomRecord :: Proxy rowlist -> Proxy row -> Record subrow

Expand Down
20 changes: 16 additions & 4 deletions src/Data/Bounded/Generic.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ instance genericBottomArgument :: Bounded a => GenericBottom (Argument a) where
instance genericBottomSum :: GenericBottom a => GenericBottom (Sum a b) where
genericBottom' = Inl genericBottom'

instance genericBottomProduct :: (GenericBottom a, GenericBottom b) => GenericBottom (Product a b) where
instance genericBottomProduct ::
( GenericBottom a
, GenericBottom b
) =>
GenericBottom (Product a b) where
genericBottom' = Product genericBottom' genericBottom'

instance genericBottomConstructor :: GenericBottom a => GenericBottom (Constructor name a) where
instance genericBottomConstructor ::
GenericBottom a =>
GenericBottom (Constructor name a) where
genericBottom' = Constructor genericBottom'

class GenericTop a where
Expand All @@ -41,10 +47,16 @@ instance genericTopArgument :: Bounded a => GenericTop (Argument a) where
instance genericTopSum :: GenericTop b => GenericTop (Sum a b) where
genericTop' = Inr genericTop'

instance genericTopProduct :: (GenericTop a, GenericTop b) => GenericTop (Product a b) where
instance genericTopProduct ::
( GenericTop a
, GenericTop b
) =>
GenericTop (Product a b) where
genericTop' = Product genericTop' genericTop'

instance genericTopConstructor :: GenericTop a => GenericTop (Constructor name a) where
instance genericTopConstructor ::
GenericTop a =>
GenericTop (Constructor name a) where
genericTop' = Constructor genericTop'

-- | A `Generic` implementation of the `bottom` member from the `Bounded` type class.
Expand Down
12 changes: 10 additions & 2 deletions src/Data/CommutativeRing.purs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ instance commutativeRingInt :: CommutativeRing Int
instance commutativeRingNumber :: CommutativeRing Number
instance commutativeRingUnit :: CommutativeRing Unit
instance commutativeRingFn :: CommutativeRing b => CommutativeRing (a -> b)
instance commutativeRingRecord :: (RL.RowToList row list, CommutativeRingRecord list row row) => CommutativeRing (Record row)
instance commutativeRingRecord ::
( RL.RowToList row list
, CommutativeRingRecord list row row
) =>
CommutativeRing (Record row)

instance commutativeRingProxy :: CommutativeRing (Proxy a)

-- | A class for records where all fields have `CommutativeRing` instances, used
-- | to implement the `CommutativeRing` instance for records.
class RingRecord rowlist row subrow <= CommutativeRingRecord rowlist row subrow | rowlist -> subrow
class
RingRecord rowlist row subrow <=
CommutativeRingRecord rowlist row subrow
| rowlist -> subrow

instance commutativeRingRecordNil :: CommutativeRingRecord RL.Nil row ()

Expand Down
3 changes: 2 additions & 1 deletion src/Data/Eq.purs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ foreign import eqNumberImpl :: Number -> Number -> Boolean
foreign import eqCharImpl :: Char -> Char -> Boolean
foreign import eqStringImpl :: String -> String -> Boolean

foreign import eqArrayImpl :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean
foreign import eqArrayImpl
:: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean

-- | The `Eq1` type class represents type constructors with decidable equality.
class Eq1 f where
Expand Down
9 changes: 7 additions & 2 deletions src/Data/Eq/Generic.purs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ instance genericEqSum :: (GenericEq a, GenericEq b) => GenericEq (Sum a b) where
genericEq' (Inr b1) (Inr b2) = genericEq' b1 b2
genericEq' _ _ = false

instance genericEqProduct :: (GenericEq a, GenericEq b) => GenericEq (Product a b) where
genericEq' (Product a1 b1) (Product a2 b2) = genericEq' a1 a2 && genericEq' b1 b2
instance genericEqProduct ::
( GenericEq a
, GenericEq b
) =>
GenericEq (Product a b) where
genericEq' (Product a1 b1) (Product a2 b2) = genericEq' a1 a2 && genericEq' b1
b2

instance genericEqConstructor :: GenericEq a => GenericEq (Constructor name a) where
genericEq' (Constructor a1) (Constructor a2) = genericEq' a1 a2
Expand Down
6 changes: 5 additions & 1 deletion src/Data/Generic/Rep.purs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ instance showProduct :: (Show a, Show b) => Show (Product a b) where
newtype Constructor (name :: Symbol) a = Constructor a

instance showConstructor :: (IsSymbol name, Show a) => Show (Constructor name a) where
show (Constructor a) = "(Constructor @" <> show (reflectSymbol (Proxy :: Proxy name)) <> " " <> show a <> ")"
show (Constructor a) = "(Constructor @"
<> show (reflectSymbol (Proxy :: Proxy name))
<> " "
<> show a
<> ")"

-- | A representation for an argument in a data constructor.
newtype Argument a = Argument a
Expand Down
9 changes: 7 additions & 2 deletions src/Data/HeytingAlgebra.purs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ instance heytingAlgebraProxy :: HeytingAlgebra (Proxy a) where
not _ = Proxy
tt = Proxy

instance heytingAlgebraRecord :: (RL.RowToList row list, HeytingAlgebraRecord list row row) => HeytingAlgebra (Record row) where
instance heytingAlgebraRecord ::
( RL.RowToList row list
, HeytingAlgebraRecord list row row
) =>
HeytingAlgebra (Record row) where
ff = ffRecord (Proxy :: Proxy list) (Proxy :: Proxy row)
tt = ttRecord (Proxy :: Proxy list) (Proxy :: Proxy row)
conj = conjRecord (Proxy :: Proxy list)
Expand All @@ -106,7 +110,8 @@ foreign import boolNot :: Boolean -> Boolean

-- | A class for records where all fields have `HeytingAlgebra` instances, used
-- | to implement the `HeytingAlgebra` instance for records.
class HeytingAlgebraRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint
class HeytingAlgebraRecord
:: RL.RowList Type -> Row Type -> Row Type -> Constraint
class HeytingAlgebraRecord rowlist row subrow | rowlist -> subrow where
ffRecord :: Proxy rowlist -> Proxy row -> Record subrow
ttRecord :: Proxy rowlist -> Proxy row -> Record subrow
Expand Down
Loading
Loading