Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prelude split into multiple files #133

Merged
merged 2 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

(install
(section lib)
(files (glob_files (lib/*.fram with_prefix stdlib))))
(files (glob_files_rec (lib/*.fram with_prefix stdlib))))
28 changes: 28 additions & 0 deletions lib/Base/Bool.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

import open Types

pub method toString = if self then "True" else "False"

pub method neg =
if self then False else True

pub method equal (oth : Bool) =
if self then oth else oth.neg

pub method neq (oth : Bool) =
if self then oth.neg else oth

pub method gt (oth : Bool) =
self && oth.neg

pub method lt {self : Bool} oth =
self.neg && oth

pub method ge (oth : Bool) =
self || oth.neg

pub method le {self : Bool} oth =
self.neg || oth
17 changes: 17 additions & 0 deletions lib/Base/Char.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

import open /Base/Types

pub method code {self : Char} =
extern dbl_chrCode : Char -> Int
ppolesiuk marked this conversation as resolved.
Show resolved Hide resolved

pub method equal = (extern dbl_eqInt : Char -> Char -> Bool) self
pub method neq = (extern dbl_neqInt : Char -> Char -> Bool) self
pub method gt = (extern dbl_gtInt : Char -> Char -> Bool) self
pub method lt = (extern dbl_ltInt : Char -> Char -> Bool) self
pub method ge = (extern dbl_geInt : Char -> Char -> Bool) self
pub method le = (extern dbl_leInt : Char -> Char -> Bool) self

pub method toString = (extern dbl_chrToString : Char -> String) self
35 changes: 35 additions & 0 deletions lib/Base/Int.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
(* This file is part of DBL, released under MIT license.
ppolesiuk marked this conversation as resolved.
Show resolved Hide resolved
* See LICENSE for details.
*)

import open Types
import open Operators

pub method toString = (extern dbl_intToString : Int -> String) self

pub method equal = (extern dbl_eqInt : Int -> Int -> Bool) self
pub method neq = (extern dbl_neqInt : Int -> Int -> Bool) self
pub method gt = (extern dbl_gtInt : Int -> Int -> Bool) self
pub method lt = (extern dbl_ltInt : Int -> Int -> Bool) self
pub method ge = (extern dbl_geInt : Int -> Int -> Bool) self
pub method le = (extern dbl_leInt : Int -> Int -> Bool) self

pub method add = (extern dbl_addInt : Int -> Int -> Int) self
pub method sub = (extern dbl_subInt : Int -> Int -> Int) self
pub method mul = (extern dbl_mulInt : Int -> Int -> Int) self

pub method div {`re : {type X} -> Unit ->[|_] X} (n : Int) =
if n.equal 0 then `re ()
else (extern dbl_divInt : Int -> Int -> Int) self n

pub method mod {`re : {type X} -> Unit ->[|_] X} (n : Int) =
if n.equal 0 then `re ()
else (extern dbl_modInt : Int -> Int -> Int) self n

pub method land = (extern dbl_andInt : Int -> Int -> Int) self
pub method lor = (extern dbl_orInt : Int -> Int -> Int) self
pub method lxor = (extern dbl_xorInt : Int -> Int -> Int) self

pub method shiftl = (extern dbl_lslInt : Int -> Int -> Int) self
pub method shiftr = (extern dbl_lsrInt : Int -> Int -> Int) self
pub method ashiftr = (extern dbl_asrInt : Int -> Int -> Int) self
27 changes: 27 additions & 0 deletions lib/Base/Operators.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

pub method fn (- .) = neg

pub method fn (+) = add
pub method fn (-) = sub
pub method fn (%) = mod
pub method fn (/) = div
pub method fn ( * ) = mul

pub method fn (==) = equal
pub method fn (!=) = neq
pub method fn (>) = gt
pub method fn (>=) = ge
pub method fn (<) = lt
pub method fn (<=) = le

pub method fn (&&&) = land
pub method fn (^^^) = lxor
pub method fn (|||) = lor
pub method fn (<<) = shiftl
pub method fn (>>) = shiftr
pub method fn (>>>) = ashiftr

pub method fn (:=) = set
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we would want some unary operator for get? Ocaml's (! .) works fine for me but maybe there is a better one

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about it. The nice thing about unary operator (! .) in OCaml is that it is a) short, and b) it has very high precedence (higher than application). I think a method get also has both of these advantages. Moreover, I see the two arguments against OCaml-like (! .):

  1. it misleadingly resembles negation in some languages (like C)
  2. it introduces some problems with operator lexing: ! and != starts with the same character, but have very different precedence (see PR Fix != operator in lexer #125).

31 changes: 31 additions & 0 deletions lib/Base/String.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

import open /Base/Types
import open /Base/Operators
import /Base/Int

pub method add = (extern dbl_strCat : String -> String -> String) self

pub method equal = (extern dbl_eqStr : String -> String -> Bool) self
pub method neq = (extern dbl_neqStr : String -> String -> Bool) self
pub method gt = (extern dbl_gtStr : String -> String -> Bool) self
pub method lt = (extern dbl_ltStr : String -> String -> Bool) self
pub method ge = (extern dbl_geStr : String -> String -> Bool) self
pub method le = (extern dbl_leStr : String -> String -> Bool) self

pub method length = (extern dbl_strLen : String -> Int) self
pub method get {`re : {type X} -> Unit ->[|_] X, self : String} (n : Int) =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since we are thinking of adding arrays, and there accessor to specyfic element of array is method at, maybe its a good idea to keep consistency and also name this method at

Copy link
Member Author

Choose a reason for hiding this comment

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

In arrays (#126) the at accessor is only for writing. Just to be able to write code like arr.at 42 := 13. For reading we have get. I don't see how to define a single accessor for both reading and writing.

if n >= 0 && n < self.length then
(extern dbl_strGet : String -> Int -> Char) self n
else `re ()

pub method toList {self : String} =
let getChar = extern dbl_strGet : String -> Int -> Char in
let rec iter (n : Int) acc =
if n == 0 then
acc
else
iter (n - 1) (getChar self (n - 1) :: acc)
in iter self.length []
13 changes: 13 additions & 0 deletions lib/Base/Types.fram
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

pub data Bool = False | True

pub data Option A = None | Some of A

pub data rec List A = [] | (::) of A, List A

pub data Pair X Y = (,) of X, Y

pub data Either X Y = Left of X | Right of Y
4 changes: 4 additions & 0 deletions lib/List.fram
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

pub let isEmpty xs =
match xs with
| [] => True
Expand Down
111 changes: 11 additions & 100 deletions lib/Prelude.fram
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
pub data Bool = False | True
(* This file is part of DBL, released under MIT license.
* See LICENSE for details.
*)

pub data Option A = None | Some of A
import /Base/Types
import /Base/Operators
import /Base/Bool
import /Base/Int
import /Base/Char
import /Base/String
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we will add more functionality to String module, and then i would expect to access that functionality with import String instead of having to write import /Base/String in repl.

Copy link
Member Author

Choose a reason for hiding this comment

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

As I answered to chr issue, the purpose of /Base/String is to have only some basic methods there. For other functions I would prefer to have a separate String module.


pub data rec List A = [] | (::) of A, List A

pub data Pair X Y = (,) of X, Y

pub data Either X Y = Left of X | Right of Y
pub open Types
pub open Operators

pub let id x = x

Expand All @@ -17,107 +21,14 @@ pub let snd (_, y) = y

pub let not b = if b then False else True

pub method toString = if self then "True" else "False"

pub method fn (+) = add
pub method fn (-) = sub
pub method fn (%) = mod
pub method fn (/) = div
pub method fn ( * ) = mul

pub method fn (==) = equal
pub method fn (!=) = neq
pub method fn (>) = gt
pub method fn (>=) = ge
pub method fn (<) = lt
pub method fn (<=) = le

pub method fn (&&&) = land
pub method fn (^^^) = lxor
pub method fn (|||) = lor
pub method fn (<<) = shiftl
pub method fn (>>) = shiftr
pub method fn (>>>) = ashiftr

pub method equal = (extern dbl_eqInt : Int -> Int -> Bool) self
pub method neq = (extern dbl_neqInt : Int -> Int -> Bool) self
pub method gt = (extern dbl_gtInt : Int -> Int -> Bool) self
pub method lt = (extern dbl_ltInt : Int -> Int -> Bool) self
pub method ge = (extern dbl_geInt : Int -> Int -> Bool) self
pub method le = (extern dbl_leInt : Int -> Int -> Bool) self

pub method toString = (extern dbl_intToString : Int -> String) self

pub method add = (extern dbl_addInt : Int -> Int -> Int) self
pub method sub = (extern dbl_subInt : Int -> Int -> Int) self
pub method mul = (extern dbl_mulInt : Int -> Int -> Int) self

pub method div {`re : {type X} -> Unit ->[|_] X} (n : Int) =
if n.equal 0 then `re ()
else (extern dbl_divInt : Int -> Int -> Int) self n

pub method mod {`re : {type X} -> Unit ->[|_] X} (n : Int) =
if n.equal 0 then `re ()
else (extern dbl_modInt : Int -> Int -> Int) self n

pub method land = (extern dbl_andInt : Int -> Int -> Int) self
pub method lor = (extern dbl_orInt : Int -> Int -> Int) self
pub method lxor = (extern dbl_xorInt : Int -> Int -> Int) self

pub method shiftl = (extern dbl_lslInt : Int -> Int -> Int) self
pub method shiftr = (extern dbl_lsrInt : Int -> Int -> Int) self
pub method ashiftr = (extern dbl_asrInt : Int -> Int -> Int) self

pub method add = (extern dbl_strCat : String -> String -> String) self

pub method equal = (extern dbl_eqStr : String -> String -> Bool) self
pub method neq = (extern dbl_neqStr : String -> String -> Bool) self
pub method gt = (extern dbl_gtStr : String -> String -> Bool) self
pub method lt = (extern dbl_ltStr : String -> String -> Bool) self
pub method ge = (extern dbl_geStr : String -> String -> Bool) self
pub method le = (extern dbl_leStr : String -> String -> Bool) self

pub method length = (extern dbl_strLen : String -> Int) self
pub method get {`re : {type X} -> Unit ->[|_] X, self : String} (n : Int) =
if n >= 0 && n < self.length then
(extern dbl_strGet : String -> Int -> Char) self n
else `re ()

pub method makeString {`re : {type X} -> Unit ->[|_] X, self : String}
(n : Int) =
if n >= 0 && n < 256 then
(extern dbl_strMake : Int -> String) n
else `re ()

pub method toList {self : String} =
let getChar = extern dbl_strGet : String -> Int -> Char in
let rec iter (n : Int) acc =
if n == 0 then
acc
else
iter (n - 1) (getChar self (n - 1) :: acc)
in iter self.length []

pub let charListToStr = (extern dbl_chrListToStr : List Char -> String)

pub method code {self : Char} =
extern dbl_chrCode : Char -> Int

pub let chr {`re : {type X} -> Unit ->[|_] X} (n : Int) =
Copy link
Collaborator

Choose a reason for hiding this comment

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

as a user i would expect to see function like this in Char module, and also those modules are a good place to add any functions (not only methods) attached to these types, but not necessarily being dependent on any value of this type. Such as chr function.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree. However, I'm against moving it into /Base/Char/ as the main purpose of this module is to contain methods that might be used without importing Char explicitly. We should create a separate module Char for that. I thing it can be done as a separate task.

if n >= 0 && n < 256 then
(extern dbl_intToChr : Int -> Char) n
else
`re ()

pub method equal = (extern dbl_eqInt : Char -> Char -> Bool) self
pub method neq = (extern dbl_neqInt : Char -> Char -> Bool) self
pub method gt = (extern dbl_gtInt : Char -> Char -> Bool) self
pub method lt = (extern dbl_ltInt : Char -> Char -> Bool) self
pub method ge = (extern dbl_geInt : Char -> Char -> Bool) self
pub method le = (extern dbl_leInt : Char -> Char -> Bool) self

pub method toString = (extern dbl_chrToString : Char -> String) self

pub let printStrLn = extern dbl_printStrLn : String ->[IO] Unit
pub let printStr = extern dbl_printStr : String ->[IO] Unit
pub let printInt = extern dbl_printInt : Int ->[IO] Unit
Expand Down
1 change: 0 additions & 1 deletion src/Eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ let extern_map =
"dbl_leStr", str_cmpop ( <= );
"dbl_strLen", str_fun (fun s -> VNum (String.length s));
"dbl_strGet", str_fun (fun s -> int_fun (fun n -> VNum (Char.code s.[n])));
"dbl_strMake", int_fun (fun n -> VStr (String.make 1 (Char.chr n)));
"dbl_chrToString", int_fun (fun c -> VStr (Char.escaped (Char.chr c)));
"dbl_chrListToStr", list_chr_fun (fun xs -> VStr (List.to_seq xs |> String.of_seq));
"dbl_chrCode", int_fun (fun c -> VNum c);
Expand Down