Jonathan Graveline pushed to branch graveline at Stefan / Typer
Commits: 451ead23 by Jonathan Graveline at 2018-08-23T20:56:11Z Documentation, work in progress
Some more tests in samples/case_test.typer
- - - - -
10 changed files:
- btl/builtins.typer - btl/case.typer - btl/do.typer - btl/list.typer - btl/pervasive.typer - btl/plain-let.typer - btl/polyfun.typer - btl/tuple.typer - samples/case_test.typer - tests/eval_test.ml
Changes:
===================================== btl/builtins.typer ===================================== @@ -255,44 +255,101 @@ Ref_make = Built-in "Ref.make" : (a : Type) ≡> a -> IO (Ref a); Ref_read = Built-in "Ref.read" : (a : Type) ≡> Ref a -> IO a; Ref_write = Built-in "Ref.write" : (a : Type) ≡> a -> Ref a -> IO Unit;
+%% %% gensym for macro - +%% Generate pseudo-unique symbol +%% At least they cannot be obtained outside macro +%% In macro you should NOT use symbol of the form ` %gensym% ...` +%% gensym = Built-in "gensym" : Unit -> IO Sexp;
-%% Function on Elab_Context +%%%% Function on Elab_Context
+%% +%% Get the current context of elaboration +%% Elab_getenv = Built-in "Elab.getenv" : Unit -> IO Elab_Context;
+%% +%% Check if a symbol is defined in a particular context +%% Elab_isbound = Built-in "Elab.isbound" : String -> Elab_Context -> Bool;
+%% +%% Check if a symbol is a constructor in a particular context +%% Elab_isconstructor = Built-in "Elab.isconstructor" : String -> Elab_Context -> Bool;
+%% +%% Check if the n'th field of a constructor is erasable +%% If the constructor isn't defined it will always return false +%% Elab_is-nth-erasable = Built-in "Elab.is-nth-erasable" : String -> Int -> Elab_Context -> Bool;
+%% +%% Check if a field of a constructor is erasable +%% If the constructor or the field aren't defined it will always return false +%% Elab_is-arg-erasable = Built-in "Elab.is-arg-erasable" : String -> String -> Elab_Context -> Bool;
+%% +%% Get n'th field of a constructor +%% It return "_" in case the field isn't defined +%% see pervasive.typer for a more convenient function +%% Elab_nth-arg' = Built-in "Elab.nth-arg" : String -> Int -> Elab_Context -> String;
+%% +%% Get the position of a field in a constructor +%% It return -1 in case something isn't defined +%% see pervasive.typer for a more convenient function +%% Elab_arg-pos' = Built-in "Elab.arg-pos" : String -> String -> Elab_Context -> Int;
+%% +%% Get the docstring associated with a symbol +%% Elab_debug-doc = Built-in "Elab.debug-doc" : String -> Elab_Context -> String;
%%%% Unit test helper IO
+%% %% Print message and/or fail (terminate) %% These message are registered like any other error +%% And location is printed before the error
+%% +%% Voluntarily fail +%% for exemple if next unit tests are not worth testing +%% +%% Takes a "section" and a "message" as argument +%% Test_fatal = Built-in "Test.fatal" : String -> String -> IO Unit; + +%% +%% Throw a warning, very similar to `Test_info` +%% but it's possible to implement a parameter for user who want it to sometimes be fatal +%% +%% Takes a "section" and a "message" as argument +%% Test_warning = Built-in "Test.warning" : String -> String -> IO Unit; + +%% +%% Just print a message with location of the call +%% +%% Takes a "section" and a "message" as argument +%% Test_info = Built-in "Test.info" : String -> String -> IO Unit;
+%% %% Get a string representing location of call ("file:line:column") - +%% Test_location = Built-in "Test.location" : Unit -> String;
-%% Do some test which print a message - +%% +%% Do some test which print a message: "[ OK]" or "[FAIL]" +%% Test_true = Built-in "Test.true" : String -> Bool -> IO Bool; Test_false = Built-in "Test.false" : String -> Bool -> IO Bool; Test_eq = Built-in "Test.eq" : (a : Type) ≡> String -> a -> a -> IO Bool;
===================================== btl/case.typer ===================================== @@ -7,6 +7,12 @@ %%%% a constructor with or without argument and %%%% argument may be sub pattern or variable) %%%% +%%%% Actualy this macro instantiate tuple when there's many variables to match +%%%% but matching an already instantiated +%%%% tuple (in a variable) is more difficult... +%%%% +%%%% Another problem is that this macro is dependent of tuple implementation +%%%%
%% Move IO outside List (from element to List) %% (Was helpful for me when translating code that used to not be IO code) @@ -30,14 +36,18 @@ in do { %% Takes a List of Sexp and generate a List of new name of the same length %% whatever are the element of the List %% - gen-vars : List Sexp -> IO (List Sexp); gen-vars vars = io-list (List_map (lambda _ -> gensym ()) vars);
-tuple-ctor : List Sexp -> Sexp; -tuple-ctor args = let +%% +%% Constructor for a tuple +%% +%% Used in patterns +%% +tuple-ctor : Sexp; +tuple-ctor = let
ctor : Sexp; ctor = Sexp_symbol "cons"; @@ -53,7 +63,6 @@ in Sexp_node (Sexp_symbol "##datacons") %% become %% `cons expr1 expr2 ... ` %% - expand-tuple-ctor : Sexp -> Sexp; expand-tuple-ctor sexp = let
@@ -62,7 +71,7 @@ expand-tuple-ctor sexp = let in Sexp_dispatch sexp (lambda s ss -> if (Sexp_eq s (Sexp_symbol "_,_")) then - (Sexp_node (tuple-ctor ss) ss) + (Sexp_node tuple-ctor ss) else (Sexp_node s ss)) (lambda _ -> sexp) @@ -71,14 +80,13 @@ in Sexp_dispatch sexp %% %% Is tuple %% - is-tuple : Sexp -> Bool; is-tuple sexp = let
sfalse = (lambda _ -> false);
in Sexp_dispatch sexp - (lambda s _ -> Sexp_eq s (tuple-ctor nil)) + (lambda s _ -> Sexp_eq s tuple-ctor) sfalse sfalse sfalse sfalse sfalse;
%% @@ -92,7 +100,6 @@ in Sexp_dispatch sexp %% (This function is now doing nothing since there's only one %% variable at any time: one expression or a tuple of expressions) %% - get-tup-exprs : Sexp -> List Sexp; get-tup-exprs sexp = let
@@ -112,7 +119,6 @@ in Sexp_dispatch sexp %% %% Some alias to clarify type of functions %% - Var = Sexp; Pat = Sexp; Pats = List Pat; @@ -129,15 +135,16 @@ is-dflt : Var -> Bool; is-dflt v = Sexp_eq dflt-var v;
%% -%% Get pattern to match as a List of pair -%% with all patterns and the user code for each branches +%% Takes a list of variable to match and a list of branch as "_=>_"-node +%% Returns pattern to match as a List of pair +%% with all patterns and user code for each branches %% - get-branches : List Sexp -> List Sexp -> List (Pair Pats Code); get-branches vars sexps = let
perr = (lambda _ -> pair (cons Pat_error nil) Code_error);
+ %% here, sexp is a node of patterns (the lhs of a "_=>_"-node) to-case : Sexp -> Pair Pats Code; to-case sexp = let
@@ -150,26 +157,37 @@ get-branches vars sexps = let in Sexp_dispatch sexp
(lambda s ss -> case (Sexp_eq (Sexp_symbol "_=>_") s) - % expecting a Sexp_node as second argument to _=>_ + %% expecting a Sexp_node as second argument to _=>_ | true => pair (tup-exprs (List_nth 0 ss Pat_error)) (List_nth 1 ss Code_error) | false => pair (cons Pat_error nil) Code_error)
perr perr perr perr perr;
+ %% map all "_=>_"-node to (patterns, body) pair helper : List Sexp -> List (Pair Pats Code); helper sexps = List_map (lambda s -> (to-case s)) sexps;
in helper sexps;
+%% +%% Takes a patterns +%% Returns a list of Bool: +%% - true at n if n'th argument is erasable +%% - false at n if n'th argument is not erasable +%% kinds : Sexp -> IO (List Bool); kinds pat = let
- serr = lambda _ -> Sexp_error; - + %% + %% errors used in Sexp_dispatch + %% + serr = lambda _ -> Sexp_error; strerr = lambda _ -> "< error >"; - - xserr = lambda _ -> (nil : List Sexp); + xserr = lambda _ -> (nil : List Sexp);
+ %% + %% Get constructor of `pat` + %% ctor : String; ctor = let ctor-name : Sexp -> String; @@ -179,12 +197,18 @@ kinds pat = let strerr strerr strerr strerr; in ctor-name pat;
+ %% + %% Get args from the `pat` node + %% args : List Sexp; args = Sexp_dispatch pat (lambda s ss -> ss) (lambda _ -> (nil : List Sexp)) xserr xserr xserr xserr;
+ %% + %% Just get a String from a symbol + %% str_of_sym : Sexp -> String; str_of_sym arg = Sexp_dispatch arg (lambda _ _ -> "< error >") @@ -194,6 +218,16 @@ kinds pat = let (lambda _ -> "< error >") (lambda _ -> "< error >");
+ %% + %% map function for all pattern's variables + %% Check if each argument are erasable or not + %% It must handle 3 things (but could handle more): + %% - all arguments are in the order of the type's declaration (named or not) + %% - all arguments are without name `(_ := x)` + %% - all arguments are with a name in any order `(name := x)` + %% What I do not expect to work is a combinaison of + %% arguments with name, other without name and all this in a random order + %% mf : Elab_Context -> Sexp -> Int -> Bool; mf env arg i = Sexp_dispatch arg (lambda s ss -> if (Sexp_eq s (Sexp_symbol "_:=_")) then @@ -228,34 +262,63 @@ in ks; %% Takes a pattern and a list of new name for each argument %% It even rename sub pattern %% - renamed-pat : Sexp -> List Sexp -> IO Sexp; renamed-pat pat names = let
- serr = lambda _ -> Sexp_error; - + %% + %% errors used in Sexp_dispatch + %% + serr = lambda _ -> Sexp_error; strerr = lambda _ -> "< error >"; + xserr = lambda _ -> (nil : List Sexp);
- xserr = lambda _ -> (nil : List Sexp); - + %% + %% true if `pat` is a tuple, false if it is a + %% single expression + %% tup : Bool; tup = is-tuple pat;
+ %% + %% Get the name of the n'th element of any tuple + %% tuple-nth : Int -> Sexp; tuple-nth n = Sexp_symbol (String_concat "%" (Int->String n));
+ %% + %% Get the constructor of the pattern as argument + %% + ctor : Sexp -> String; + ctor pat = Sexp_dispatch pat + (lambda s _ -> ctor s) + (lambda s -> s) + strerr strerr strerr strerr; + + %% + %% Map function to rename `pat` with symbol in `names` + %% + %% `kinds` is curried before being passed to `List_mapi` + %% and tell if an argument is erasable + %% + %% Produce code according to argument kind + %% and if it already use explicit field or not + %% mf : List Bool -> Sexp -> Int -> Sexp; mf kinds v i = Sexp_dispatch v (lambda sym ss -> if (Sexp_eq sym (Sexp_symbol "_:=_")) then if (List_nth i kinds false) then + %% %% if client use multiple name for the same erasable args, %% I expect it to not compile... + %% (Sexp_node sym ss) else (Sexp_node sym (cons (List_nth 0 ss Sexp_error) (cons (List_nth i names Sexp_error) nil))) else if tup then + %% %% tuples argument are all implicit so we must take special care of those + %% (Sexp_node (Sexp_symbol "_:=_") (cons (tuple-nth i) (cons (List_nth i names Sexp_error) nil))) else @@ -266,12 +329,6 @@ renamed-pat pat names = let else (List_nth i names Sexp_error)) serr serr serr serr; - - ctor : Sexp -> String; - ctor pat = Sexp_dispatch pat - (lambda s _ -> ctor s) - (lambda s -> s) - strerr strerr strerr strerr;
in do { pat <- IO_return pat; @@ -286,14 +343,18 @@ in do { %% Takes an Sexp as argument and IO_return `IO true` if it is a pattern %% (i.e. a constructor with or without argument) %% - is-pat : Pat -> IO Bool; is-pat pat = let
- err = lambda _ -> IO_return false; - + %% + %% errors used in Sexp_dispatch + %% + err = lambda _ -> IO_return false; serr = lambda _ -> "< error >";
+ %% + %% Get a String from a Sexp_symbol + %% sym-str : Sexp -> String; sym-str sexp = Sexp_dispatch sexp (lambda _ _ -> serr ()) @@ -314,38 +375,55 @@ in Sexp_dispatch pat err err err err;
%% -%% Takes two pattern and IO_return `IO true` if the two pattern -%% has the same constructor +%% Takes two pattern and return true if the two pattern +%% has the same constructor %% - is-same-ctor : Pat -> Pat -> Bool; is-same-ctor p0 p1 = let
+ %% + %% error used in Sexp_dispatch + %% err = lambda _ -> Pat_error;
+ %% + %% Get the constructor of a pattern + %% ctor-of : Pat -> Sexp; ctor-of p = Sexp_dispatch p (lambda s _ -> s) (lambda s -> Sexp_symbol s) err err err err;
+%% Compare head of node of both pattern in Sexp_eq (ctor-of p0) (ctor-of p1);
%% %% Get variable introduced by a constructor %% -%% Takes a pattern as argument and IO_return each arguments -%% of the constructor which is a variable (as opposed to a sub pattern) +%% Takes a pattern as argument and return each arguments +%% of the constructor which is a variable (as opposed to a sub pattern) %% - introduced-vars : Pat -> IO (List Var); introduced-vars pat = let
+ %% + %% error used in Sexp_dispatch + %% serr = lambda _ -> IO_return (pair 0 nil);
+ %% + %% List of kind of pattern argument + %% ks : IO (List Bool); ks = kinds pat;
+ %% + %% Function to fold each argument of the pattern + %% The Int is used internaly to keep track of argument index + %% It is useful to know where is the variable in `ks` to get its kind + %% (kind is actualy only erasable or not here) + %% ff : IO (Pair Int (List Sexp)) -> Sexp -> IO (Pair Int (List Sexp)); ff p v = let
@@ -389,7 +467,7 @@ in Sexp_dispatch pat IO_return (case p | pair _ xs => xs); }) - (lambda _ -> IO_return nil) % constructor as a unique symbol (as `true`) + (lambda _ -> IO_return nil) % constructor as a unique symbol (`true`, etc) (lambda _ -> IO_return nil) (lambda _ -> IO_return nil) % error (lambda _ -> IO_return nil) (lambda _ -> IO_return nil); % error
@@ -397,7 +475,6 @@ in Sexp_dispatch pat %% Wrap the third argument (`fun`) with a `let` definition for each variables %% Names are taken from `rvars` and definition are taken from `ivars` %% - wrap-vars : List Var -> List Var -> Code -> Code; wrap-vars ivars rvars fun = List_fold2 (lambda fun v0 v1 -> %% @@ -408,13 +485,15 @@ wrap-vars ivars rvars fun = List_fold2 (lambda fun v0 v1 -> fun ivars rvars;
%% -%% Take a List of branches and IO_return a List of the first pattern in each branches +%% Take a List of branches and return a List of the first pattern in each branches %% (I must keep the order from input to ouput) %% - head-pats : List (Pair Pats Code) -> List Pat; head-pats ps = let
+ %% + %% Map function just returning the first patterns for one branch + %% mf : Pair Pats Code -> Pat; mf p = case p | pair pats _ => (List_nth 0 pats Pat_error); @@ -423,10 +502,9 @@ in List_map mf ps;
%% %% Takes a pattern as argument and -%% IO_return a List of sub pattern for that branch -%% the List contain dflt-var if it has a variable which is not a pattern +%% return a List of sub pattern for that branch +%% the List contain dflt-var if it has a variable which is not a pattern %% - pattern-sub-pats : Pat -> IO (List Pat); pattern-sub-pats pat = let
@@ -439,7 +517,6 @@ pattern-sub-pats pat = let %% if another branch has a sub pattern %% at this position %% - map-arg : Var -> IO Var; map-arg arg = do { b <- is-pat arg; @@ -462,11 +539,10 @@ in Sexp_dispatch pat err err err err;
%% -%% Takes a List of similar pattern (i.e. a pattern of same constructor) -%% IO_return a List of gensym variable if there's is a sub pattern -%% and a default variable when there's no sub pattern +%% Takes a List of similar pattern (i.e. patterns with same constructor) +%% Returns a List of gensym variable if there is a sub pattern +%% and a default variable when there is no sub pattern %% - pattern-sub-pats-vars : List Var -> List (Pair Pat (List (Pair Var Var))) -> IO (List Var); pattern-sub-pats-vars rvars branches = let
@@ -504,13 +580,12 @@ pattern-sub-pats-vars rvars branches = let in List_foldl ff (IO_return nil) pats;
%% -%% IO_return a List of old/new variables names +%% Return a List of old/new variables names %% -%% new variable should be identical for each branches -%% but old variable (from user code) are arbitrary -%% (except for explicit field pattern...) +%% New variable should be identical for each branches +%% but old variable (from user code) are arbitrary +%% (except for explicit field pattern...) %% - pattern-term : Pat -> List Var -> IO (List (Pair Var Var)); pattern-term pat rvars = let
@@ -530,22 +605,24 @@ in do { %% %% Type of one partition of branches (one branch with some possible child branches) %% -%% pair of renamed pat, variables old/new in each branch and List of next branch -%% a branch with a pattern with old/new variables for each next branches -%% and each next branches from this branch +%% Pair of +%% Triplet of renamed pat, +%% original variable, +%% variables old/new and original pattern in each branch +%% List of next branch %% - part-type = Pair (Triplet Pat (List Var) (List (Pair Pat (List (Pair Var Var))))) (List (Pair Pats Code));
%% -%% IO_return a pair of renamed and partitioned pattern -%% (i.e. a Pair of renamed pattern, introduced variables, old pattern and tail of branches) -%% (Yeah, I need old pattern to get sub pattern at some point) +%% Takes a list of branches (pair of (patterns, body)) +%% Return a list of partition %% - partition-branches : List (Pair Pats Code) -> IO (List part-type); partition-branches branches = let
+ %% + %% Remove the first pattern of all `branches` + %% tl-branches : List (Pair Pats Code); tl-branches = let
@@ -555,6 +632,9 @@ partition-branches branches = let
in List_map mf branches;
+ %% + %% Pull the first patterns of all branches and keep the tails + %% hd-pair : List (Pair Pat (Pair Pats Code)); hd-pair = let
@@ -567,11 +647,15 @@ partition-branches branches = let %% %% Type for first step partition %% - %% Pair of List sorted with similar head (head as in first) + %% Pair of List sorted with similar head + %% they are similar when they have the same constructor %% - pre-part-type = Pair (List Pat) (List (Pair Pats Code));
+ %% + %% First step partition (see `pre-part-type`) + %% from `branches` + %% pre-parts : List pre-part-type; pre-parts = let
@@ -602,6 +686,9 @@ partition-branches branches = let
in List_foldl ff nil hd-pair;
+ %% + %% `pre-part-type` to `part-type` + %% parts : IO (List part-type); parts = let
@@ -633,24 +720,48 @@ in do {
%% %% reminder -%% part-type = Pair (Triplet Pat (List Var) (List (Pair Pat (List (Pair Var Var))))) (List (Pair Pats Code)); +%% +%% part-type = Pair +%% (Triplet Pat (List Var) (List (Pair Pat (List (Pair Var Var))))) +%% (List (Pair Pats Code)); %%
+%% +%% There's a need to merge branch because default branch may be anywhere +%% +%% (I tried to consider default branches similar to everything but it failed in some way +%% So here we are...) +%% merge-dflt : List part-type -> Option part-type -> List part-type; merge-dflt parts odflt = let
+ %% %% It must be bugged in one way or another... - - %% preppend child branches in case we see a default branch before a normal branch - + %% + + %% + %% Preppend child branches if we see a default branch before a normal branch + %% + %% exemple: + %% | (x,_,y) => ... + %% | (x,k,z) => ... + %% In this exemple (and in Typer) I can suppose `y != z` (or there will be warning/error) + %% If we take the first case first we did not match `k` and cannot jump to the next + %% But since `y != z` we can safely take the second first + %% preppend : Pat -> List (Pair Pat (List (Pair Var Var))) -> List (Pair Pats Code) -> part-type -> part-type; preppend pat vars branches part = case part | pair p b => (case p | triplet _ lv v => pair (triplet pat lv (List_concat vars v)) (List_concat branches b));
- %% append child branches in case we see more than one default branches - + %% + %% Append child branches if we see more than one default branches + %% + %% exemple: + %% | (x,_,z) => ... + %% | (x,_,_) => ... + %% append : Pat -> List (Pair Pat (List (Pair Var Var))) -> List (Pair Pats Code) -> part-type -> part-type; append pat vars branches part = case part @@ -674,9 +785,11 @@ in case parts | none => nil);
%% -%% takes some branches and preppend default variable to smaller branches +%% Takes some branches and preppend default variable to smaller branches +%% +%% (Sub-pattern introduce new variable but if +%% it fail suplementary variable must match something else) %% - adjust-len : List (Pair Pats Code) -> List (Pair Pats Code); adjust-len branches = let
@@ -710,27 +823,38 @@ in List_map (preppend-dflt max-len) branches;
%% %% reminder +%% %% part-type = Pair %% (Triplet %% Pat (List Var) (List (Pair Pat (List (Pair Var Var))))) %% (List (Pair Pats Code)); %% - compile-case : List Var -> List (Pair Pats Code) -> IO Code; compile-case subjects branches = let
subject = (List_nth 0 subjects Var_error);
+ %% + %% Get partition of branches + %% parts : IO (List part-type); parts = do { ps <- partition-branches branches; IO_return (merge-dflt ps none); };
+ %% + %% Takes a decomposed `part-type` and generate code from it + %% translate-sub-pats : List Var -> List (Pair Pat (List (Pair Var Var))) -> List (Pair Pats Code) -> IO Code; translate-sub-pats rvars pats-vars branches = let - + + %% + %% Here we consider sub-pattern with necessary suplementary variable, + %% append them to branches and generate code + %% + recursion : List (Pair Pat (List (Pair Var Var))) -> List (Pair Pats Code) -> IO Code; recursion pats-vars branches = let @@ -772,8 +896,10 @@ compile-case subjects branches = let sub-pats-vars <- sub-pats-vars; r <- IO_return (List_concat sub-pats-vars (List_tail subjects));
+ %% %% As for constructor we remove variable if it is always a default %% variable without any corresponding sub pattern + %%
r <- IO_return (List_foldl (lambda o v -> if (is-dflt v) then @@ -801,6 +927,9 @@ compile-case subjects branches = let
in recursion pats-vars branches;
+ %% + %% Generate code from one `part-type` + %% translate-part : part-type -> IO Code; translate-part branch = case branch | pair patterns branches => (case patterns @@ -809,6 +938,9 @@ compile-case subjects branches = let IO_return (quote (_=>_ (uquote pat) (uquote sub-cases))); });
+ %% + %% Generate code from all partition + %% translate : List part-type -> IO Code; translate parts = do { branches <- io-list (List_map translate-part parts); @@ -827,8 +959,8 @@ in do { %%% The macro we want. %%%
-rec-case : List Sexp -> IO Sexp; -rec-case args = let +case-impl : List Sexp -> IO Sexp; +case-impl args = let
case0 : List Sexp -> IO Sexp; case0 args = let @@ -876,4 +1008,4 @@ rec-case args = let in (Sexp_dispatch (List_nth 0 args Sexp_error) case1 err err err err err);
-case-macro = macro rec-case; +case-macro = macro case-impl;
===================================== btl/do.typer ===================================== @@ -14,11 +14,21 @@ %% %% fun is a command, %% -%% do may contain do because it returns a command. +%% `do` may contain `do` because it returns a command. %%
+%% +%% Operator of assignment in `do` block +%% assign = Sexp_symbol "_<-_";
+%% +%% Takes one of `;`-separated command in `do` block +%% Returns the left-hand side symbol +%% or a default symbol +%% +%% `lhs <- rhs;` +%% get-sym : Sexp -> Sexp; get-sym sexp = let
@@ -32,6 +42,13 @@ get-sym sexp = let dflt-sym dflt-sym dflt-sym dflt-sym dflt-sym; % there must be a command
+%% +%% Takes one of `;`-separated command in `do` block +%% Returns the right-hand side command +%% `lhs <- rhs;` +%% or +%% `rhs;` +%% get-op : Sexp -> Sexp; get-op sexp = let
@@ -52,17 +69,22 @@ get-op sexp = let
in if (Sexp_eq op (Sexp_symbol "")) then Sexp_error else op;
+%% +%% Takes a block (`{...}`) +%% Parse the block and returns the list of command inside the block +%% get-decl : List Sexp -> List Sexp; get-decl args = let
err = lambda _ -> cons Sexp_error nil;
- % Expecting a Block of command separated by ";" + %% Expecting a Block of command separated by ";"
node = Sexp_dispatch (List_nth 0 args Sexp_error)
(lambda _ _ -> cons Sexp_error nil) err err err err
+ %% `Parser_newest` use the most recent environment (lambda l -> Parser_newest l);
in node; @@ -76,7 +98,14 @@ in node; %% this way a-sym is defined within b-op and so on %% a-sym is now just `a` and not `IO a` %% +%% ( It could be possible to use `IO Ref` rather than a new variable +%% for each command, but will it be useful? ) +%%
+%% +%% Takes the list of command inside `do` block +%% This is the `main` of macro `do` +%% set-fun : List Sexp -> Sexp; set-fun args = let
===================================== btl/list.typer ===================================== @@ -11,6 +11,8 @@
%%%% List type
+%% +%% List's type is currently in pervasive.typer %% %% FIXME: "List : ?" should be sufficient but triggers %% macro `type` isn't actually defined where this file is included @@ -24,6 +26,19 @@
%%%% List functions
+%% +%% Get the length of a list in O(N) times where N is the length +%% +%% Alternative (tail recursive): +%% +%% length xs = let +%% helper : (a : Type) ≡> Int -> List a -> Int; +%% helper len xs = case xs +%% | nil => len +%% | cons hd tl => helper (len + 1) tl; +%% in helper 0 xs; +%% +%% length : (a : Type) ≡> List a -> Int; length xs = case xs | nil => 0 @@ -40,21 +55,39 @@ head1 xs = case xs | nil => none | cons hd tl => some hd;
+%% +%% Takes a list +%% Returns `some x` where x is the first element of the list +%% or none if the list is empty +%% head : (a : Type) ≡> List a -> Option a; head xs = case xs | cons x _ => some x | nil => none;
+%% +%% Takes a list +%% Returns the same list without it's first element +%% The tail of `nil` is still `nil` +%% tail : (a : Type) ≡> List a -> List a; tail xs = case xs | nil => nil | cons hd tl => tl;
+%% +%% Apply a function to all element of a list +%% +%% (Should be as `map` of every functional language) +%% map : (a : Type) ≡> (b : Type) ≡> (a -> b) -> List a -> List b; map f = lambda xs -> case xs | nil => nil | cons x xs => cons (f x) (map f xs);
+%% +%% As `map` but user's function also takes element index as last argument +%% mapi : (a : Type) ≡> (b : Type) ≡> (a -> Int -> b) -> List a -> List b; mapi = lambda f -> lambda xs -> let helper : (a -> Int -> b) -> Int -> List a -> List b; @@ -63,6 +96,10 @@ mapi = lambda f -> lambda xs -> let | cons x xs => cons (f x i) (helper f (i + 1) xs); in helper f 0 xs;
+%% +%% As `map` but with 2 list at the same time +%% If they are not of the same length the result is just as long as the smallest +%% map2 : (a : Type) ≡> (b : Type) ≡> (c : Type) ≡> (a -> b -> c) -> List a -> List b -> List c; map2 = lambda f -> lambda xs -> lambda ys -> case xs | nil => nil @@ -70,6 +107,9 @@ map2 = lambda f -> lambda xs -> lambda ys -> case xs | nil => nil % error | cons y ys => cons (f x y) (map2 f xs ys);
+%% +%% As `foldl` but user's function also takes element index as last argument +%% foldli : (a : Type) ≡> (b : Type) ≡> (a -> b -> Int -> a) -> a -> List b -> a; foldli = lambda f -> lambda o -> lambda xs -> let helper : (a -> b -> Int -> a) -> Int -> a -> List b -> a; @@ -78,7 +118,9 @@ foldli = lambda f -> lambda o -> lambda xs -> let | cons x xs => helper f (i + 1) (f o x i) xs; in helper f 0 o xs;
+%% %% Fold 2 List as long as both List are non-empty +%% fold2 : (a : Type) ≡> (b : Type) ≡> (c : Type) ≡> (a -> b -> c -> a) -> a -> List b -> List c -> a; fold2 = lambda f -> lambda o -> lambda xs -> lambda ys -> case xs | cons x xs => ( case ys @@ -86,16 +128,27 @@ fold2 = lambda f -> lambda o -> lambda xs -> lambda ys -> case xs | nil => o ) % may be an error | nil => o; % may or may not be an error
+%% +%% (Should be as any `fold right` of functional language) +%% foldr : (a : Type) ≡> (b : Type) ≡> (b -> a -> a) -> List b -> a -> a; foldr = lambda f -> lambda xs -> lambda i -> case xs | nil => i | cons x xs => f x (foldr f xs i);
+%% +%% Takes a function and a list +%% Returns `some x` if x is the first element on the list to return true +%% when applied to the function or `none` if there was no such element +%% find : (a : Type) ≡> (a -> Bool) -> List a -> Option a; find = lambda f -> lambda xs -> case xs | nil => none | cons x xs => case f x | true => some x | false => find f xs;
+%% +%% Get the n'th element of a list or a default if the list is smaller +%% nth : (a : Type) ≡> Int -> List a -> a -> a; nth = lambda n -> lambda xs -> lambda d -> case xs | nil => d @@ -104,19 +157,34 @@ nth = lambda n -> lambda xs -> lambda d -> case xs | true => x | false => nth (n - 1) xs d;
+%% +%% Reverse the element of a list +%% Common usage is `reverse ll nil` which reverse the list ll +%% reverse : (a : Type) ≡> List a -> List a -> List a; reverse = lambda l -> lambda t -> case l | nil => t | cons hd tl => reverse tl (cons hd t);
+%% +%% Concat two list with first argument first +%% concat : (a : Type) ≡> List a -> List a -> List a; concat = lambda l -> lambda t -> reverse (reverse l nil) t;
+%% +%% Apply all element of the list to an object through a function +%% (Should be as `fold-left` of any functional language) +%% foldl : (a : Type) ≡> (b : Type) ≡> (a -> b -> a) -> a -> List b -> a; foldl = lambda f -> lambda i -> lambda xs -> case xs | nil => i | cons x xs => foldl f (f i x) xs;
+%% +%% Takes a function and a list +%% Returns the list with element removed if the function return true on those element +%% remove : (a : Type) ≡> (a -> Bool) -> List a -> List a; remove = lambda f -> lambda l -> case l | nil => nil @@ -125,8 +193,10 @@ remove = lambda f -> lambda l -> case l | false => cons x (remove f xs) );
+%% %% Merge two List to a List of Pair %% Both List must be of same length +%% merge : (a : Type) ≡> (b : Type) ≡> List a -> List b -> List (Pair a b); merge = lambda xs -> lambda ys -> case xs | cons x xs => ( case ys @@ -134,8 +204,11 @@ merge = lambda xs -> lambda ys -> case xs | nil => nil ) % error | nil => nil;
+%% %% `Unmerge` a List of Pair -%% The two functions name said it all +%% The two functions' name say it all +%% + map-fst : (a : Type) ≡> (b : Type) ≡> List (Pair a b) -> List a; map-fst = lambda xs -> let mf : Pair a b -> a; @@ -148,12 +221,30 @@ map-snd = lambda xs -> let mf p = case p | pair _ y => y; in map mf xs;
+%% %% Is argument List empty -empty : (a : Type) ≡> List a -> Bool; -empty = lambda xs -> Int_eq (length xs) 0; +%% +empty? : (a : Type) ≡> List a -> Bool; +%% +%% O(N): +%% empty? = lambda xs -> Int_eq (length xs) 0; +%% +%% O(1): +empty? = lambda xs -> case xs + | nil => true + | _ => false;
+%%%% %%%% Sorting List +%%%%
+%% +%% Using Quicksort but not in-place +%% Takes a comparison function and a list +%% Returns the same list but sorted +%% +%% If comparison is `>` then the list start with the smallest element +%% sort : (a : Type) ≡> (a -> a -> Bool) -> List a -> List a; sort = lambda o -> lambda l -> let
@@ -161,12 +252,19 @@ sort = lambda o -> lambda l -> let sortp = lambda p -> lambda lt -> lambda gt -> lambda l -> case p | none => nil | some (pp) => ( case l - | nil => ( let + | nil => ( let + + %% Sort the two sub-list + %% With the head as pivot ltp : List a; ltp = sortp (head1 lt) nil nil (tail lt); gtp : List a; gtp = sortp (head1 gt) nil nil (tail gt); + + %% concatenate because we can't do it in-place in concat ltp (cons pp gtp) ) | cons x xs => ( case (o x pp) + + %% partition with `p` as pivot | true => sortp p lt (cons x gt) xs | false => sortp p (cons x lt) gt xs ) @@ -176,6 +274,12 @@ in sortp (head1 l) nil nil (tail l);
%%%% Some algo on sorted list
+%% +%% Find an element with a shortcut because the list is sorted +%% Takes a comparison function, a function to match, an element and a list +%% +%% (...maybe to parametric for what it does, this function is useless) +%% sfind : (a : Type) ≡> (a -> a -> Bool) -> (a -> Bool) -> a -> List a -> Option a; sfind = lambda o -> lambda f -> lambda a -> lambda l -> case l | nil => none @@ -187,6 +291,10 @@ sfind = lambda o -> lambda f -> lambda a -> lambda l -> case l ) );
+%% +%% Takes a function and a list +%% Returns all element which return true when applied to the function +%% sall : (a : Type) ≡> (a -> Bool) -> List a -> List a; sall = lambda f -> lambda l -> case l | nil => nil @@ -195,11 +303,18 @@ sall = lambda f -> lambda l -> case l | false => sall f xs );
-sexist : (a : Type) ≡> (a -> a -> Bool) -> (a -> Bool) -> a -> List a -> Bool; -sexist = lambda o -> lambda f -> lambda a -> lambda l -> case (sfind o f a l) +%% +%% Is some element member of the list? +%% +sexist? : (a : Type) ≡> (a -> a -> Bool) -> (a -> Bool) -> a -> List a -> Bool; +sexist? = lambda o -> lambda f -> lambda a -> lambda l -> case (sfind o f a l) | none => false | some _ => true;
+%% +%% Insert an element into an already sorted list +%% Takes a comparison function, an element to insert and a list +%% sinsert : (a : Type) ≡> (a -> a -> Bool) -> a -> List a -> List a; sinsert = lambda o -> lambda a -> lambda l -> case l | nil => cons a l @@ -208,6 +323,12 @@ sinsert = lambda o -> lambda a -> lambda l -> case l | false => cons x (sinsert o a xs) );
+%% +%% Takes a comparison function, a pivot and a list +%% Returns the sub-list with all element "greater" than pivot +%% (For exemple if the comparison function is `>` then it returns +%% all element greater or equal to pivot) +%% ssup : (a : Type) ≡> (a -> a -> Bool) -> a -> List a -> List a; ssup = lambda o -> lambda a -> lambda l -> case l | nil => nil @@ -216,6 +337,12 @@ ssup = lambda o -> lambda a -> lambda l -> case l | false => ssup o a xs );
+%% +%% Takes a comparison function, a pivot and a list +%% Returns the sub-list with all element "smaller" than pivot +%% (For exemple if the comparison function is `>` then it returns +%% all element smaller than pivot) +%% sinf : (a : Type) ≡> (a -> a -> Bool) -> a -> List a -> List a; sinf = lambda o -> lambda a -> lambda l -> case l | nil => nil @@ -228,6 +355,9 @@ sinf = lambda o -> lambda a -> lambda l -> case l %%%% Array from List %%%%
+%% +%% Takes a list and returns an array with the same element in the same order +%% List->Array : (a : Type) ≡> List a -> Array a; List->Array xs = let
===================================== btl/pervasive.typer ===================================== @@ -362,12 +362,6 @@ type-impl = lambda (x : List Sexp) ->
type_ = macro type-impl;
-%%%% Backward compatibility - -length = List_length; -head = List_head1; -tail = List_tail; - %%%% Tuples
%% Sample tuple: a module holding Bool and its constructors. @@ -585,10 +579,10 @@ _|_ = let lib = load "btl/polyfun.typer" in lib._|_; %% because of circular dependency...
%% -%% A macro using `load` for testing purpose +%% A macro using `load` for unit testing purpose %% -%% takes a file name (String) as argument -%% return variable named `exec-test` from the loaded file +%% Takes a file name (String) as argument +%% Return variable named `exec-test` from the loaded file %% %% `exec-test` should be a command doing unit tests %% for other purpose than that just use `load` directly!
===================================== btl/plain-let.typer ===================================== @@ -11,16 +11,34 @@ %% List_reverse = list.reverse; %% List_tail = list.tail;
+%% +%% The idea is to use unique identifier in a first let +%% and then assign those first identifier to the original symbol +%% +%% Useful for auto-generated code (macro, ...) +%% + +%% +%% Takes the plain input of macro `plain-let` +%% impl : List Sexp -> IO Sexp; impl args = let
+ %% error use in Sexp_dispatch serr = lambda _ -> Sexp_error;
+ %% Takes an assignment statement and return a new + %% symbol for the resulting variable + %% For function it only rename the function name and not the argument gen-sym : Sexp -> IO Sexp; gen-sym arg = let
+ %% error use in Sexp_dispatch io-serr = lambda _ -> IO_return Sexp_error;
+ %% Get a `gensym` symbol + %% I can rename a function name (not the argument) + %% or just a symbol rename : Sexp -> IO Sexp; rename sexp = Sexp_dispatch sexp (lambda _ ss -> do { @@ -36,6 +54,7 @@ impl args = let (IO_return Sexp_error)) io-serr io-serr io-serr io-serr io-serr;
+ %% Takes an assignment statement and return the right-hand side get-def : Sexp -> Sexp; get-def arg = Sexp_dispatch arg (lambda s ss -> if (Sexp_eq s (Sexp_symbol "_=_")) then @@ -43,6 +62,7 @@ impl args = let (Sexp_error)) serr serr serr serr serr;
+ %% Takes an assignment statement and return the left-hand side get-var : Sexp -> Sexp; get-var arg = Sexp_dispatch arg (lambda s ss -> if (Sexp_eq s (Sexp_symbol "_=_")) then @@ -50,6 +70,7 @@ impl args = let (Sexp_error)) serr serr serr serr serr;
+ %% Takes a list of assignment and return a list of pair of `gensym` and definition (rhs) get-sym-def : List Sexp -> IO (List (Pair Sexp Sexp)); get-sym-def args = do { r <- List_foldl (lambda o arg -> do { @@ -61,6 +82,8 @@ impl args = let IO_return r; };
+ %% Takes a list of assignment and the output of `get-sym-def` + %% Returns a list of pair of `gensym` and original symbol get-var-sym : List Sexp -> List (Pair Sexp Sexp) -> IO (List (Pair Sexp Sexp)); get-var-sym args syms = let
@@ -77,12 +100,19 @@ impl args = let IO_return r; };
+ %% Takes a list of assignment and a body (likely using those assignment) + %% Returns a `let ... in ...` construction let-in : Sexp -> Sexp -> Sexp; let-in decls body = Sexp_node (Sexp_symbol "let_in_") (cons decls (cons body nil));
+ %% Takes a list of assignment and separate them with `;` let-decls : List Sexp -> Sexp; let-decls decls = Sexp_node (Sexp_symbol "_;_") decls;
+ %% Takes lists of pairs (`gensym`,definition) and (`gensym`,original symbol) + %% and the body (likely using original symbol) + %% Returns + %% let [gensym] = [definition] ... in let [original symbol] = [gensym] in [body] gen-code : List (Pair Sexp Sexp) -> List (Pair Sexp Sexp) -> Sexp -> Sexp; gen-code sym-def var-sym body = let
@@ -96,6 +126,7 @@ impl args = let
in let-in (let-decls decls0) (let-in (let-decls decls1) body);
+ %% Returns a list of assignment from a "_;_"-node get-decls : Sexp -> List Sexp; get-decls sexp = let
@@ -108,6 +139,8 @@ impl args = let xserr xserr xserr xserr xserr;
in do { + %% get list of pair and use it to generate `plain-let` + defs <- IO_return (get-decls (List_nth 0 args Sexp_error)); body <- IO_return (List_nth 1 args Sexp_error); sym-def <- get-sym-def defs; @@ -116,7 +149,9 @@ in do { IO_return (gen-code sym-def var-sym body); };
+%% just calling the `impl` function in a macro plain-let-macro = macro (lambda args -> do { r <- impl args; + %% Sexp_debug_print r; IO_return r; });
===================================== btl/polyfun.typer ===================================== @@ -1,12 +1,15 @@ %%%% %%%% Polymorphic function %%%% +%%%% ( ^ I'm not sure about the name) %%%% (Just a `case` at function definition level) %%%%
+%% error use in Sexp_dispatch serr : (a : Type) ≡> a -> Sexp; serr = lambda _ -> Sexp_error;
+%% other error for Sexp_dispatch xserr : (a : Type) ≡> a -> List Sexp; xserr = lambda _ -> (nil : List Sexp);
@@ -14,15 +17,25 @@ xserr = lambda _ -> (nil : List Sexp); %% List_map = list.map; %% List_tail = list.tail;
+%% +%% Takes a function node with its argument and the body as a second argument +%% Returns a definition with a `;` +%% fun-decl : Sexp -> Sexp -> Sexp; fun-decl decl body = Sexp_node (Sexp_symbol "_;_") (cons (quote ( (uquote decl) = (uquote body) )) nil); +%% +%% Sexp_node (Sexp_symbol "_;_") (cons +%% (Sexp_node (Sexp_symbol "_=_") (cons decl (cons body nil))) +%% nil); +%%
-%% Sexp_node (Sexp_symbol "_;_") (cons -%% (Sexp_node (Sexp_symbol "_=_") (cons decl (cons body nil))) -%% nil); - +%% +%% Takes a function node with it's argument (`f x y`) +%% Returns a list of the symbol of every argument +%% (for `f (x : Int) y` it returns a list containing symbol "x" and "y") +%% fun-args : Sexp -> List Sexp; fun-args decl = Sexp_dispatch decl (lambda s ss -> let @@ -40,6 +53,10 @@ fun-args decl = Sexp_dispatch decl in List_map mf ss) xserr xserr xserr xserr xserr;
+%% +%% Takes a list of "_=>_"-node +%% Returns a list of pair of (pattern, body) +%% fun-cases : List Sexp -> List (Pair Sexp Sexp); fun-cases args = let
@@ -58,6 +75,10 @@ fun-cases args = let
in List_map mf args;
+%% +%% Takes argument list and list of pair of (pattern, body) +%% Returns a function with a `case` on argument for each pattern +%% cases-to-sexp : List Sexp -> List (Pair Sexp Sexp) -> Sexp; cases-to-sexp vars cases = let
@@ -77,14 +98,22 @@ in Sexp_node (Sexp_symbol "case_") (cons (List_nth 0 vars Sexp_error)) (List_map mf cases))) nil);
+%% +%% The macro we want +%% +%% I expect a function node and then "_=>_"-nodes +%% _|_ = macro (lambda args -> let
+ %% function with argument (e.g. `f x y`) decl : Sexp; decl = List_nth 0 args Sexp_error;
+ %% symbol to match fargs : List Sexp; fargs = fun-args decl;
+ %% pattern for argument match cases : List (Pair Sexp Sexp); cases = fun-cases (List_tail args);
===================================== btl/tuple.typer ===================================== @@ -2,6 +2,8 @@ %%%% macro '_,_' for tuple %%%%
+%% +%% Here's an exemple similar to tuple from `load` %% %% Sample tuple: a module holding Bool and its constructors. %% @@ -53,17 +55,26 @@ in do { %% Takes a List of Sexp and generate a List of new name of the same length %% whatever are the element of the List %% - gen-vars : List Sexp -> IO (List Sexp); gen-vars vars = io-list (List_map (lambda _ -> gensym ()) vars);
+%% +%% Reference for tuple's implicit field name +%% +%% Takes a list of vars (it could actually only takes a length) +%% Returns symbol `%n` with n from 0 to the length of the argument +%% gen-tuple-names : List Sexp -> List Sexp; gen-tuple-names vars = List_mapi (lambda _ i -> Sexp_symbol (String_concat "%" (Int->String i))) vars;
+%% +%% Takes a list +%% Returns a list of the same length with every element set to "?" symbol +%% gen-deduce : List Sexp -> List Sexp; gen-deduce vars = List_map (lambda _ -> Sexp_symbol "?") @@ -73,12 +84,17 @@ gen-deduce vars = List_map %%% Access one tuple's element %%%
-%% tuple-nth : (tup-type : Type) ≡> (elem-type : Type) ≡> tup-type -> Int -> elem-type; - +%% +%% This is a macro with conceptualy this signature: +%% tuple-nth : (tup-type : Type) ≡> (elem-type : Type) ≡> tup-type -> Int -> elem-type; +%% +%% Returns the n'th element of the tuple +%% tuple-nth = macro (lambda args -> let
nerr = lambda _ -> (Int->Integer (-1));
+ %% argument `n` of this macro n : Integer; n = Sexp_dispatch (List_nth 1 args Sexp_error) (lambda _ _ -> nerr ()) @@ -86,9 +102,11 @@ tuple-nth = macro (lambda args -> let (lambda n -> n) nerr nerr;
+ %% implicit tuple field name elem-sym : Sexp; elem-sym = Sexp_symbol (String_concat "%" (Integer->String n));
+ %% tuple, argument of this macro tup : Sexp; tup = List_nth 0 args Sexp_error;
@@ -99,10 +117,18 @@ in IO_return (Sexp_node (Sexp_symbol "__.__") (cons tup (cons elem-sym nil))) %%% Affectation, unwraping tuple %%%
+%% +%% syntax: +%% (x, y, z) <- p; +%% +%% and then `x`, `y`, `z` are defined from tuple's element 0, 1, 2 +%% assign-tuple = macro (lambda args -> let
xserr = lambda _ -> (nil : List Sexp);
+ %% Expect a ","-node + %% Returns variables get-tup-elem : Sexp -> List Sexp; get-tup-elem sexp = Sexp_dispatch sexp (lambda s ss -> @@ -112,6 +138,8 @@ assign-tuple = macro (lambda args -> let (nil)) xserr xserr xserr xserr xserr;
+ %% map every tuple's variable + %% using `tuple-nth` to assign element to variable mf : Sexp -> Sexp -> Int -> Sexp; mf t arg i = Sexp_node (Sexp_symbol "_=_") (cons arg (cons (Sexp_node (Sexp_symbol "tuple-nth") @@ -137,12 +165,18 @@ wrap-vars ivars rvars fun = List_fold2 (lambda fun v0 v1 -> (quote (let (uquote v1) = (uquote v0) in (uquote fun)))) fun ivars rvars;
+%% +%% Takes a list of values as Sexp (like 1, 1.0, "str", etc) +%% Returns a tuple containing those values +%% make-tuple-impl : List Sexp -> IO Sexp; make-tuple-impl values = let
+ %% map tuple element declaration mf1 : Sexp -> Sexp -> Sexp; mf1 name value = Sexp_node (Sexp_symbol "_::_") (cons name (cons value nil));
+ %% map tuple element value mf2 : Sexp -> Sexp -> Sexp; mf2 value nth = Sexp_node (Sexp_symbol "_:=_") (cons nth (cons value nil));
@@ -168,6 +202,9 @@ in do { IO_return affect; };
+%% +%% Macro to instantiate a tuple +%% make-tuple = macro (lambda args -> do { r <- make-tuple-impl args; r <- IO_return r; @@ -175,7 +212,10 @@ make-tuple = macro (lambda args -> do { });
%% - +%% Macro returning the type of a tuple +%% +%% Takes element's type as argument +%% tuple-type = macro (lambda args -> let
mf : Sexp -> Sexp -> Sexp;
===================================== samples/case_test.typer ===================================== @@ -49,6 +49,12 @@ dflt2 a b c = case (a,b,c) | (true,false,_) => 1 | (_,_,_) => 0;
+dflt3 : Bool -> Bool -> Bool -> Int; +dflt3 a b c = case (a,b,c) + | (_,_,true) => 777 + | (_,false,false) => 888 + | (_,_,_) => 999; + nand : Bool -> Bool -> Bool; nand b0 b1 = case (b0,b1) | (true,true) => false @@ -80,6 +86,10 @@ test-dflt = do { r18 <- Test_true "nand" (nand false true); r19 <- Test_true "nand" (nand false false);
+ r20 <- Test_eq "dflt3" (dflt3 true false false) 888; + r21 <- Test_eq "dflt3" (dflt3 true true false) 999; + r22 <- Test_eq "dflt3" (dflt3 true false true) 777; + part1 <- IO_return (and r0 (and r1 (and r2 (and r3 (and r4 (and r5 (and r6 r7)))))));
@@ -88,7 +98,9 @@ test-dflt = do {
part3 <- IO_return (and r16 (and r17 (and r18 r19)));
- success <- IO_return (and part1 (and part2 part3)); + part4 <- IO_return (and r20 (and r21 r22)); + + success <- IO_return (and part1 (and part2 (and part3 part4)));
if success then (Test_info "MACRO CASE" "test on default succeeded")
===================================== tests/eval_test.ml ===================================== @@ -264,9 +264,9 @@ let _ = test_eval_eqv_named nil' = datacons List' nil; my_list' = (cons' 1 nil');"
- "length my_list; - head my_list; - head (tail my_list)" + "list.length my_list; + list.head my_list; + list.head (list.tail my_list)"
"4; some 1; some 2"
View it on GitLab: https://gitlab.com/monnier/typer/commit/451ead238502f3e4bde114c17a312622de74...
Afficher les réponses par date