Make $ special

This commit is contained in:
2024-11-30 15:51:06 -08:00
parent d2bbf681ea
commit 71cf4f39f5
7 changed files with 173 additions and 29 deletions

View File

@@ -5,7 +5,7 @@
- [ ] TCO? Probably needed in browser, since v8 doesn't do it. bun and JavaScriptCore do support it. - [ ] TCO? Probably needed in browser, since v8 doesn't do it. bun and JavaScriptCore do support it.
- [x] deconstructing `let` (and do arrows) - [x] deconstructing `let` (and do arrows)
- [x] Fix string printing to be js instead of weird Idris strings - [x] Fix string printing to be js instead of weird Idris strings
- [ ] make $ special - [x] make $ special
- Makes inference easier, cleaner output, and allows `foo $ \ x => ...` - Makes inference easier, cleaner output, and allows `foo $ \ x => ...`
- remove hack from Elab.infer - remove hack from Elab.infer
- [ ] Support @ on the LHS - [ ] Support @ on the LHS

View File

@@ -76,12 +76,10 @@ _<>>_ : ∀ a. SnocList a → List a → List a
Lin <>> ys = ys Lin <>> ys = ys
(xs :< x) <>> ys = xs <>> x :: ys (xs :< x) <>> ys = xs <>> x :: ys
-- TODO this is special cased in some languages, maybe for easier -- This is now handled by the parser, and LHS becomes `f a`.
-- inference? Figure out why. -- infixr 0 _$_
-- Currently very noisy in generated code (if nothing else, optimize it out?) -- _$_ : ∀ a b. (a -> b) -> a -> b
infixr 0 _$_ -- f $ a = f a
_$_ : a b. (a -> b) -> a -> b
f $ a = f a
infixr 8 _×_ infixr 8 _×_
infixr 2 _,_ infixr 2 _,_

View File

@@ -16,7 +16,7 @@
}, },
{ {
"name": "keyword.newt", "name": "keyword.newt",
"match": "\\b(data|where|do|class|uses|instance|case|of|let|if|then|else|forall|∀|in|U|module|import|ptype|pfunc|infix|infixl|infixr)\\b" "match": "\\b(λ|=>|->|→|:=|\\$|data|where|do|class|uses|instance|case|of|let|if|then|else|forall|∀|in|U|module|import|ptype|pfunc|infix|infixl|infixr)\\b"
}, },
{ {
"name": "string.js", "name": "string.js",

View File

@@ -1,5 +1,7 @@
module Prelude module Prelude
id : a. a a
id x = x
data Bool : U where data Bool : U where
True False : Bool True False : Bool
@@ -15,14 +17,27 @@ _||_ : Bool → Bool → Bool
True || _ = True True || _ = True
False || b = b False || b = b
infixr 5 _&&_
_&&_ : Bool Bool Bool
False && b = False
True && b = b
infixl 6 _==_ infixl 6 _==_
class Eq a where class Eq a where
_==_ : a a Bool _==_ : a a Bool
infixl 6 _/=_
_/=_ : a. {{Eq a}} a a Bool
a /= b = not (a == b)
data Nat : U where data Nat : U where
Z : Nat Z : Nat
S : Nat -> Nat S : Nat -> Nat
pred : Nat Nat
pred Z = Z
pred (S k) = k
instance Eq Nat where instance Eq Nat where
Z == Z = True Z == Z = True
S n == S m = n == m S n == S m = n == m
@@ -61,19 +76,23 @@ _<>>_ : ∀ a. SnocList a → List a → List a
Lin <>> ys = ys Lin <>> ys = ys
(xs :< x) <>> ys = xs <>> x :: ys (xs :< x) <>> ys = xs <>> x :: ys
-- TODO this is special cased in some languages, maybe for easier -- This is now handled by the parser, and LHS becomes `f a`.
-- inference? Figure out why. -- infixr 0 _$_
-- Currently very noisy in generated code (if nothing else, optimize it out?) -- _$_ : ∀ a b. (a -> b) -> a -> b
infixr 0 _$_ -- f $ a = f a
_$_ : a b. (a -> b) -> a -> b
f $ a = f a
infixr 8 _×_ infixr 8 _×_
infixr 2 _,_ infixr 2 _,_
data _×_ : U U U where data _×_ : U U U where
_,_ : A B. A B A × B _,_ : A B. A B A × B
infixl 6 _<_ fst : a b. a × b a
fst (a,b) = a
snd : a b. a × b b
snd (a,b) = b
infixl 6 _<_ _<=_
class Ord a where class Ord a where
_<_ : a a Bool _<_ : a a Bool
@@ -82,6 +101,8 @@ instance Ord Nat where
Z < S _ = True Z < S _ = True
S n < S m = n < m S n < S m = n < m
_<=_ : a. {{Eq a}} {{Ord a}} a a Bool
a <= b = a == b || a < b
-- Monad -- Monad
class Monad (m : U U) where class Monad (m : U U) where
@@ -95,6 +116,9 @@ ma >>= amb = bind ma amb
_>>_ : {0 m} {{Monad m}} {0 a b} -> m a -> m b -> m b _>>_ : {0 m} {{Monad m}} {0 a b} -> m a -> m b -> m b
ma >> mb = mb ma >> mb = mb
join : m. {{Monad m}} {0 a} m (m a) m a
join mma = mma >>= id
-- Equality -- Equality
infixl 1 _≡_ infixl 1 _≡_
@@ -137,6 +161,14 @@ class Applicative (f : U → U) where
return : {0 a} a f a return : {0 a} a f a
_<*>_ : {0 a b} -> f (a b) f a f b _<*>_ : {0 a b} -> f (a b) f a f b
class Traversable (t : U U) where
traverse : {f : U U} {{appf : Applicative f}} {a : U} {b : U} (a f b) t a f (t b)
instance Applicative Maybe where
return a = Just a
Nothing <*> _ = Nothing
Just f <*> fa = f <$> fa
infixr 2 _<|>_ infixr 2 _<|>_
class Alternative (m : U U) where class Alternative (m : U U) where
_<|>_ : {0 a} m a m a m a _<|>_ : {0 a} m a m a m a
@@ -167,7 +199,6 @@ instance Mul Nat where
Z * _ = Z Z * _ = Z
S n * m = m + n * m S n * m = m + n * m
infixl 7 _-_ infixl 7 _-_
class Sub a where class Sub a where
_-_ : a a a _-_ : a a a
@@ -189,6 +220,17 @@ pfunc sconcat : String → String → String := `(x,y) => x + y`
instance Concat String where instance Concat String where
_++_ = sconcat _++_ = sconcat
pfunc jsEq uses (True False) : a. a a Bool := `(_, a, b) => a == b ? True : False`
instance Eq Int where
a == b = jsEq a b
instance Eq String where
a == b = jsEq a b
instance Eq Char where
a == b = jsEq a b
data Unit : U where data Unit : U where
MkUnit : Unit MkUnit : Unit
@@ -274,6 +316,21 @@ instance Monad List where
bind Nil amb = Nil bind Nil amb = Nil
bind (x :: xs) amb = amb x ++ bind xs amb bind (x :: xs) amb = amb x ++ bind xs amb
-- This is traverse, but we haven't defined Traversable yet
mapA : m. {{Applicative m}} {0 a b} (a m b) List a m (List b)
mapA f Nil = return Nil
mapA f (x :: xs) = return _::_ <*> f x <*> mapA f xs
mapM : m. {{Monad m}} {0 a b} (a m b) List a m (List b)
mapM f Nil = pure Nil
mapM f (x :: xs) = do
b <- f x
bs <- mapM f xs
pure (b :: bs)
class HasIO (m : U -> U) where class HasIO (m : U -> U) where
liftIO : a. IO a m a liftIO : a. IO a m a
@@ -306,9 +363,6 @@ instance Show Int where
pfunc ord : Char -> Int := `(c) => c.charCodeAt(0)` pfunc ord : Char -> Int := `(c) => c.charCodeAt(0)`
infix 6 _<=_
pfunc _<=_ uses (True False) : Int -> Int -> Bool := `(x,y) => (x <= y) ? True : False`
pfunc unpack : String -> List Char pfunc unpack : String -> List Char
:= `(s) => { := `(s) => {
let acc = Nil(Char) let acc = Nil(Char)
@@ -327,9 +381,15 @@ pfunc pack : List Char → String := `(cs) => {
} }
` `
pfunc debugStr : a. a String := `(_, obj) => { pfunc debugStr uses (natToInt listToArray) : a. a String := `(_, obj) => {
const go = (obj) => { const go = (obj) => {
if (obj?.tag) { if (obj?.tag === '_::_') {
let stuff = listToArray(undefined,obj)
return '['+(stuff.map(go).join(', '))+']'
}
if (obj?.tag === 'S') {
return ''+natToInt(obj)
} else if (obj?.tag) {
let rval = '('+obj.tag let rval = '('+obj.tag
for(let i=0;;i++) { for(let i=0;;i++) {
let key = 'h'+i let key = 'h'+i
@@ -398,3 +458,80 @@ span {a} f xs = go xs Nil
go (x :: xs) left = if f x go (x :: xs) left = if f x
then go xs (x :: left) then go xs (x :: left)
else (reverse left, x :: xs) else (reverse left, x :: xs)
instance Show Nat where
show n = show (natToInt n)
enumerate : a. List a List (Nat × a)
enumerate {a} xs = go Z xs
where
go : Nat List a List (Nat × a)
go k Nil = Nil
go k (x :: xs) = (k,x) :: go (S k) xs
filter : a. (a Bool) List a List a
filter pred Nil = Nil
filter pred (x :: xs) = if pred x then x :: filter pred xs else filter pred xs
drop : a. Nat -> List a -> List a
drop _ Nil = Nil
drop Z xs = xs
drop (S k) (x :: xs) = drop k xs
take : a. Nat -> List a -> List a
take Z xs = Nil
take _ Nil = Nil
take (S k) (x :: xs) = x :: take k xs
getAt : a. Nat List a Maybe a
getAt _ Nil = Nothing
getAt Z (x :: xs) = Just x
getAt (S k) (x :: xs) = getAt k xs
splitOn : a. {{Eq a}} a List a List (List a)
splitOn {a} v xs = go Nil xs
where
go : List a List a List (List a)
go acc Nil = reverse acc :: Nil
go acc (x :: xs) = if x == v
then reverse acc :: go Nil xs
else go (x :: acc) xs
class Inhabited a where
default : a
instance a. Inhabited (List a) where
default = Nil
getAt! : a. {{Inhabited a}} Nat List a a
getAt! _ Nil = default
getAt! Z (x :: xs) = x
getAt! (S k) (x :: xs) = getAt! k xs
instance a. Applicative (Either a) where
return b = Right b
Right x <*> Right y = Right (x y)
Left x <*> _ = Left x
Right x <*> Left y = Left y
instance a. Monad (Either a) where
pure x = Right x
bind (Right x) mab = mab x
bind (Left x) mab = Left x
instance Monad Maybe where
pure x = Just x
bind Nothing mab = Nothing
bind (Just x) mab = mab x
elem : a. {{Eq a}} a List a Bool
elem v Nil = False
elem v (x :: xs) = if v == x then True else elem v xs
-- TODO no empty value on my `Add`, I need a group..
-- sum : ∀ a. {{Add a}} → List a → a
-- sum xs = foldl _+_
pfunc trace uses (debugStr) : a. String -> a -> a := `(_, msg, a) => { console.log(msg,debugStr(_,a)); return a }`

View File

@@ -76,12 +76,10 @@ _<>>_ : ∀ a. SnocList a → List a → List a
Lin <>> ys = ys Lin <>> ys = ys
(xs :< x) <>> ys = xs <>> x :: ys (xs :< x) <>> ys = xs <>> x :: ys
-- TODO this is special cased in some languages, maybe for easier -- This is now handled by the parser, and LHS becomes `f a`.
-- inference? Figure out why. -- infixr 0 _$_
-- Currently very noisy in generated code (if nothing else, optimize it out?) -- _$_ : ∀ a b. (a -> b) -> a -> b
infixr 0 _$_ -- f $ a = f a
_$_ : a b. (a -> b) -> a -> b
f $ a = f a
infixr 8 _×_ infixr 8 _×_
infixr 2 _,_ infixr 2 _,_

View File

@@ -296,8 +296,9 @@ ifThenElse = do
c <- term c <- term
pure $ RIf fc a b c pure $ RIf fc a b c
-- This hits an idris codegen bug if parseOp is last and Lazy term' : Parser Raw
term = caseExpr
term' = caseExpr
<|> caseLet <|> caseLet
<|> letExpr <|> letExpr
<|> lamExpr <|> lamExpr
@@ -306,6 +307,15 @@ term = caseExpr
-- Make this last for better error messages -- Make this last for better error messages
<|> parseOp <|> parseOp
term = do
t <- term'
rest <- many ((,) <$> getPos <* keyword "$" <*> term')
pure $ apply t rest
where
apply : Raw -> List (FC,Raw) -> Raw
apply t [] = t
apply t ((fc,x) :: xs) = RApp fc t (apply x xs) Explicit
varname : Parser String varname : Parser String
varname = (ident <|> uident <|> keyword "_" *> pure "_") varname = (ident <|> uident <|> keyword "_" *> pure "_")

View File

@@ -11,6 +11,7 @@ keywords = ["let", "in", "where", "case", "of", "data", "U", "do",
"", "forall", "", "forall",
"class", "instance", "class", "instance",
"if", "then", "else", "if", "then", "else",
"$", "λ",
"->", "", ":", "=>", ":=", "=", "<-", "\\", "_", "|"] "->", "", ":", "=>", ":=", "=", "<-", "\\", "_", "|"]
checkKW : String -> Token Kind checkKW : String -> Token Kind